Django: Как проверить, что форма с объектом отношения m2m уже существует или является «unique_together»? - PullRequest
0 голосов
/ 20 сентября 2019

Я тестирую формы и модели вложений в Django.В моем проекте человек может ввести departure, arrival (названия городов) и выбрать день недели (пн-пт).Может быть, он ездит каждый «вторник» из Амстердама в Париж.Я хотел, чтобы это созвездие было уникальным - просто для удовольствия.Таким образом, если другой пользователь входит в тот же маршрут, отношение должно быть связано с тем же Car.object.

Models.py

class Person(models.Model):
    name = models.CharField(max_length=255, blank=False, unique=True)
    route = models.ManyToManyField('Car')
    def __str__(self):
        return self.name


class Car(models.Model):
    name = models.CharField(max_length=255, blank=False, unique=True)
    weekdays = models.ForeignKey('Week', null=True, blank=False, on_delete=models.SET_NULL)
    departure = models.CharField(max_length=255, blank=False)
    arrival = models.CharField(max_length=255, blank=False)

    class Meta:
        unique_together = ['weekdays', 'departure', 'arrival'] # --- Unique combination

    def __str__(self):
        return self.name

class Week(models.Model):
    day = models.CharField(max_length=255, blank=False, unique=True)

    def __str__(self):
        return self.day

views.py

class RouteCreateView(CreateView):
    model = Person
    template_name ="testa/create_route.html"
    form_class = RouteForm
    success_url = reverse_lazy('testa:testa_home')

    def form_valid(self, form):
        return super().form_valid(form)

forms.py

class RouteForm(forms.ModelForm):
    # --- apply ChoiceField
    day = forms.ModelChoiceField(queryset=None)
    car_name = forms.CharField()
    departure = forms.CharField()
    arrival = forms.CharField()

    class Meta:
        model = Person
        fields = [ 
            'name'
            ]


    def __init__(self, *args, **kwargs):
        super(RouteForm, self).__init__(*args, **kwargs)
        self.fields['day'].queryset = Week.objects.all()


    def save(self, commit=True):
        personData = super().save(commit)
        data = self.cleaned_data
        carData = Car(name=data['car_name'], weekdays=data['day'], departure=data['departure'], arrival=data['arrival'])
        if commit:
            carData.save()
            personData.route.add(carData)  # --- save m2m relation
        return personData

Если я введу два раза, например, «« Вторник »из Амстердама в Париж», то, очевидно, появляется сообщение об ошибке, это сообщение об ошибке (немецкое), говорящее мне, что у меня естьдвойная запись / ключ.


Вопрос

Так что мой save() метод не работает, потому что мне нужна какая-то логика, так что Django берет существующий car.object или создает новый - если это не двойная запись.Но я не знаю с чего начать?Самым простым способом было бы получить какой-то ответ от мета-опции моей модели Car.unique_together, поэтому ", если это" ошибка двойного ключа ", тогда возьмите существующий объект" .Есть ли способ получить ответ?И какие значения это были бы, только ошибки, не могли найти ни одного намека в документе?Или я должен попробовать какую-то логику с exists()

Это была моя идея / подход нового сохранения () ?

def save(self, commit=True):
    personData = super().save(commit)
    data = self.cleaned_data
    carData = Car(name=data['car_name'], weekdays=data['day'], departure=data['departure'], arrival=data['arrival'])
    if commit:
        # Check if database sends unique_together response
        # if yes 
        if Car.Meta.unique_together is True:
            getAlternative = Car.object.get(Meta.unique_together) # --- get the object which already exist
            personData.route.add(getAlternative)  # --- save m2m relation
        # if not 
        else:
            carData.save()  # --- save object
            personData.route.add(carData)  # --- save m2m relation
    return personData

очевидноя получаю сообщение об ошибке: объект типа «Автомобиль» не имеет атрибута «Мета»

1 Ответ

1 голос
/ 21 сентября 2019

Theres get_or_create для такого случая использования: https://docs.djangoproject.com/en/2.2/ref/models/querysets/#get-or-create

...
car, created = Car.objects.get_or_create(
    weekdays=data['day'],
    departure=data['departure'],
    arrival=data['arrival'],
    defaults = dict(name=data['car_name']),
)
personData.route.add(car)
...

Очевидно, что данное имя игнорируется, если найден другой автомобиль с такими же неделями, отъездом, прибытием.

Я предлагаюпоставить код для создания автомобиля и добавления маршрута в транзакцию .atomic () https://docs.djangoproject.com/en/2.2/topics/db/transactions/#django.db.transaction.atomic

...