将模型的实例值传递给django中的另一个不同的模型实例

时间:2018-04-02 20:43:10

标签: django inheritance django-models

我对django比较新,并且在将一些信息从一个模型传递到另一个模型时遇到问题。它不是完全继承,而是确保父模型在创建子模型时传递某些信息。所以我有两个模型,一个用于事件,另一个用于事件。事件通过管理员运行,当您创建事件时,它还会为该事件创建事件。我的问题是每个事件都在一个特定的城市,我希望它将城市值传递给它创建的事件,以便我可以在过滤器中使用该城市值。应该注意,事件不是事件,因此这不仅仅是多表继承。我如何传递这个值?

Models.py

# The events are models that contain the what and where.
class Event(models.Model):
    class Meta:
        verbose_name_plural = 'Events'
        verbose_name = 'Event'

    created = models.DateTimeField(auto_now=False, auto_now_add=True, blank = False, null = False, verbose_name = 'Creation Date')
    #Date Event was edited for the last time
    updated = models.DateTimeField(auto_now=True, auto_now_add=False, blank = False, null = False, verbose_name = 'Updated')
    #Name of the event
    name = models.CharField(max_length = 400, null=True, blank = False, verbose_name = 'Name')
    #Event Description
    description = models.TextField(max_length = 10000, null=True, blank = True, verbose_name = 'Description')
    #Event City
    city = models.ForeignKey(City, null=True, blank = False, verbose_name = 'City')
    #Event Location
    location = ChainedForeignKey(
        ProfileVenue,
        chained_field="city",
        chained_model_field="city",
        show_all=False,
        auto_choose=True,
        sort=True,
        default=1,)
    #Price Entity
    price = models.ForeignKey(Price, null=True, blank = True,)
    #Max Number of participants
    max_participants = models.IntegerField(null=True, blank = False, verbose_name = 'Nr. Participants')
    #Event Language
    language = models.ForeignKey(Language, null = True, blank = False)
    #Event Type
    event_type = models.ForeignKey(EventType, null = True, blank =False, verbose_name='Event Type')
    #---------------------------------------------------------------------------
    def __unicode__(self):
        return "%s:%s" % (self.name, self.location.name)


class Occurrence(models.Model):
    class Meta:
        verbose_name_plural = 'Sessions'
        verbose_name = 'Session'

    created = models.DateTimeField(auto_now=False,
        auto_now_add=True, blank = False, null = False, verbose_name = 'Creation Date')
    updated = models.DateTimeField(auto_now=True,
        auto_now_add=False, blank = False, null = False, verbose_name = 'Updated')
    event = models.ForeignKey(Event,
        on_delete=models.CASCADE)
    '''
    city = ChainedForeignKey(
        Event,
        chained_field="city",
        chained_model_field="city",
        show_all=False,
        auto_choose=True,
        sort=True)
    '''
    teacher = models.ForeignKey(ProfileTeacher,
        null=True, blank = True, verbose_name = 'Teacher')
    students = models.ManyToManyField(ProfileStudent,
        verbose_name = 'Students', blank=True)
    # Max number of students for this group
    max_participants = models.IntegerField(null=False,
        blank=False, default=5, verbose_name='Max Nr Participants')
    # Date and Time for this session
    date = models.DateTimeField(auto_now=False,
        auto_now_add=False, null=True, blank=True, verbose_name='Date')
    # Duration of the class
    duration = models.DurationField(default=timedelta(), verbose_name='Duration')
    # Language Levels
    language_level = models.ForeignKey(LanguageLevel,
        null=True, blank=True, verbose_name='Language Level')
    # True of teacher was assigned to class
    teacher_assigned = models.BooleanField(
        default=False, blank=True)
    # Status of the Occurrence
    # Active --> Class has been created
    # Canceled --> Canceled by human admin
    # Auto Canceled --> Canceled by the Automation System
    # Due --> Class finished. Student Evaluated. Teacher Can get Extraction.
    STATUS = (
        (1, ('ACTIVE')),
        (2, ('CANCELED')),
        (3, ('DUE')),
        (4, ('AUTO CANCELED')),
    )
    status = models.IntegerField(choices=STATUS, default=1)
    # Evaluated by teacher: True if a teacher evaluated all students
    students_ev_by_teacher = models.BooleanField(default=False, verbose_name='Alumnos evaluados')
    # If true Send Mails when occurrence canceled to all teachers that are not assigned and students
    send_cancel_mail = models.BooleanField(default=True, verbose_name='Enviar Email Cancelar')
    # friendlly url
    slug = models.SlugField(max_length=300, verbose_name='Occurrence Url', blank=True, null=True)

在创建事件时创建Occurence的事件管理表单

class EventForm(forms.ModelForm):
    list_filter = ['city']
    #Frequecy type for periodical events
    FREQUENCY = (
        ('NEVER', ('Nunca')),
        # ('DAILY', _('Every Day')),
        ('WEEKDAY', ('Cada Semana')),
        # ('WEEKLY', _('Every Week')),
        # ('BIWEEKLY', _('Every 2 Weeks')),
        # ('MONTHLY', _('Every Month')),
    )
    # Weekday choices
    WEEKDAYS = (
        ( 0, ('Lunes')),
        ( 1, ('Martes')),
        ( 2, ('Miercoles')),
        ( 3, ('Jueves')),
        ( 4, ('Viernes')),
        ( 5, ('Sabado')),
        ( 6, ('Domingo')),
    )
    #Date of the first Occurrence
    start_date = forms.SplitDateTimeField(
        widget = widgets.AdminSplitDateTime(),
        help_text='Date and hour of the Event.',
        required= True,
        )
    #Limit Date for last Occurrence: no hour needed
    end_date = forms.SplitDateTimeField(
        widget = widgets.AdminSplitDateTime(),
        required = False,
        help_text='Date and hour of the Event.',
        )

    #Event frequency tipe: weekly and never supported only
    freq = forms.ChoiceField(
        choices=FREQUENCY,
        initial='WEEKDAY',
        label = 'Tipo Periodicidad'
        )

    #The event wwill occure on this weekday once a week until the end date
    weekday = forms.ChoiceField(
        choices=WEEKDAYS,
        widget=forms.RadioSelect(),
        initial=1
        )

    #Event Duration in hours: stored as timedelta in database
    duration = forms.DurationField(
        initial='01:00:00',
        )

    #Class Meta
    class Meta:
        model = Event
        fields = ('name',
                  'event_type',
                  'description',
                  'city',
                  'location',
                  'language',
                  'price',
                  'max_participants',
                  'start_date',
                  'end_date',
                  'freq',
                  'weekday',
                  'duration',
                  )

    #End Date Validation:
    def clean_end_date(self):
        if self.cleaned_data['end_date'] > self.cleaned_data['start_date']:
            return self.cleaned_data['end_date']
        else:
            raise ValidationError('End-Date should be higher than Start-Date!', code='invalid')

    #End Date Validation: Occurences shall not be created when an event is updated
    #This will create too many objects and confusion.


    #Save the Validated Form
    def save(self, commit=True):
        #Getting the cleaned data
        freq = self.cleaned_data.get('freq', None)
        start_date = self.cleaned_data.get('start_date', None)
        end_date = self.cleaned_data.get('end_date', None)
        weekday = int(self.cleaned_data.get('weekday', None))
        duration = self.cleaned_data.get('duration', None)
        #Saving the Event
        self.instance.save()
        #Loading Language Levels
        levels = LanguageLevel.objects.all()
        #Calculate Max Participants for Occurrences
        #This shall be a function of the type of the event
        max_participants = 5;
        #Create Occurrences from dates(see dateutil.rrule doc's for details):
        if freq == 'NEVER':
            for level in levels:
                #Check for Future Occurrences:
                oc = Occurrence(
                    date=start_date,
                    event=self.instance,
                    duration=duration,
                    max_participants=max_participants,
                    language_level=level,
                    )
                oc.save()
        #One per week until End_Date
        elif freq == 'WEEKDAY':
            oc_dates = rrule(WEEKLY, dtstart = start_date, byweekday = weekday, until=end_date)
            for oc_date in oc_dates:
                for level in levels:
                    oc = Occurrence(
                        date=oc_date,
                        event=self.instance,
                        duration=duration,
                        max_participants=max_participants,
                        language_level=level,
                        )
                    oc.save()
        #Saving the Event
        return super(EventForm, self).save(commit=commit)

2 个答案:

答案 0 :(得分:0)

您有一个事件的外键,您可以使用该外键访问该城市,例如使用属性:

class Occurrence(models.Model):
    [...]
    @property
    def city(self):
        return self.event.city

无需在数据库中复制数据。

答案 1 :(得分:0)

感谢@DanielRoseman提供了这个答案。我的问题是我没有使用双下划线语法,这使我能够访问我的"事件"属性。即.filter(event__city=cityId)。其完整文件here