2017-01-20 4 views
0

Это похоже на то, что должно быть довольно простым, и что-то, что должно быть общепринятым, но чем больше я пытаюсь найти ответ, тем более запутанным я получаю.django - Использование одной формы для создания двух экземпляров модели

У меня есть модель события, связанная с несколькими другими моделями, которым нужны события, поэтому я создал для нее отдельную модель событий. Теперь я хочу создать событие, когда создаю модель работы, но мне трудно понять, как это сделать.

В моем поле работы у меня есть отношение OneToOneField к событию, и единственное, что мне нужно решить, в то время, когда я делаю событие, - это продолжительность.

Упрощенная модель работы может выглядеть следующим образом:

class Job(models.Model): 
    customer = models.ForeignKey(Customer) 
    address = models.CharField(max_length=100, verbose_name="Job Address", null=False, blank=False) 
    city = models.CharField(max_length=100, verbose_name="City", null=True, blank=True) 
    state = models.CharField(max_length=2, verbose_name="State", null=True, blank=True) 
    zip = models.CharField(max_length=5, verbose_name="Zip Code", null=True, blank=True) 
    # Simply need to set duration 
    event = models.OneToOneField(Event, on_delete=models.CASCADE, null=False, blank=False) 

И упрощенная модель событий может выглядеть следующим образом:

class Event(models.Model): 

    TIME_LIST = (
     (1, "0:30"), 
     (2, "1:00"), 
     (3, "1:30"), 
     (4, "2:00"), 
     (5, "2:30"), 
     (6, "3:00"), 
     (7, "3:30"), 
     (8, "4:00"), 
     (9, "4:30"), 
     (10, "5:00"), 
     (11, "5:30"), 
     (12, "6:00"), 
     (13, "6:30"), 
     (14, "7:00"), 
     (15, "7:30"), 
     (16, "8:00"), 
    ) 

    title = models.CharField(max_length=255) 
    employee = models.ForeignKey(Employee, null=True, blank=True) 
    start_time = models.DateTimeField(null=True, blank=True) 
    end_time = models.DateTimeField(null=True, blank=True) 
    range = RecurrenceField(null=True, blank=True) 
    duration = models.IntegerField(choices=TIME_LIST, null=True, blank=True) 
    is_all_day = models.BooleanField(default=False, null=False, blank=False) 

Я использую родовой CBVS, так просто:

class JobCreate(CreateView): 
    template_name = 'jobs/create.html' 
    success_url = '/schedule/add/' 
    form_class = JobCreateForm 

    def get_success_url(self): 
     return self.success_url + str(self.object.id) 

И моя форма может быть просто:

class JobCreateForm(forms.ModelForm): 
    class Meta: 
     model = Job 
     fields = [ 
      'customer', 
      'address', 
      'city', 
      'state', 
      'zip', 
     ] 

Что мне нужно - это способ, которым я могу сделать поле выбора в течение продолжительности в моей форме задания, а затем создать новый экземпляр события, подключить event_id в поле события моей модели работы и отправить его все за один присест.

Я посмотрел на inlineformset_factory, который кажется, что он должен быть тем, что мне нужно, и я продолжаю получать с ним ошибки, так что это либо неправильная идея, либо я использую ее неправильно. Я попробовал пару миксинов, которые другие предложили, и они кажутся излишними, и я все равно не работал на меня.

ответ

1

Вы можете создать вторую форму для Event и визуализировать ее в своем шаблоне. Затем, на ваш взгляд, вы можете сохранить его первым, создав событие, затем сохраните форму Job и установите для нее связанное событие только что созданному.

В качестве альтернативы (как я бы это сделал), если вы предпочитаете одну форму, вы можете добавить поле продолжительности в форму своей работы и переопределить функцию формы save. Переопределяюсь сохранить может выглядеть примерно так

def save(self, commit=True): 
    e = Event.objects.create(duration=self.cleaned_data.get('duration')) 

    job = super().save(commit=False) 
    job.event = e 
    job.save() 
    return job 

FormSets действительно для создания нескольких форм, так что в вашем случае, как вы используете OneToOneField (таким образом, только создание требует единой формы, чтобы создать единый связанный объект) это Wouldn Есть смысл использовать их.

+0

спасибо. Так оно и было. Я знал, что это должно быть просто. –

0

Я только понял, что ответ, который я принял, был не совсем правильным. По какой-то причине (магия django) save вызывается более одного раза, один для получения данных и один раз для сохранения, поэтому он делал два экземпляра событий каждый раз при создании задания. Другая проблема заключалась в том, что событие также должно быть сохранено до сохранения задания или попытки запустить job.save() выдает ошибку. Я решил это, используя следующий код.

def save(self, commit=True): 
    job = super(JobCreateForm, self).save(commit=False) 
    if commit: 
     event = Event(duration=self.cleaned_data.get('duration'), title=self.cleaned_data.get('customer')) 
     event.save() 
     job.event = event 
     job.save() 
    return job 
Смежные вопросы