Django: многозначные поля и целостность данных - PullRequest
1 голос
/ 04 мая 2010

Допустим, у меня есть Человек, который управляет системой инвентаризации. У каждого человека есть несколько автомобилей, и у каждого автомобиля есть очень большое количество деталей (скажем, тысяч).

Человек, Боб, использует форму Джанго для создания Автомобиля. Теперь Боб начинает создавать некоторые части. Только на уровне формы Джанго знает, что Детали принадлежат какому-то конкретному автомобилю, и что в поле Parts.ForeignKey (Car) должен быть выбран только конкретный автомобиль. При создании части вы должны связываться с конструктором формы или подобным, чтобы ограничить выбор автомобилей только автомобилями, принадлежащими Бобу.

Кажется не совсем правильным или безопасным обеспечивать это право собственности на уровне формы. Во-первых, кажется, что Автомобили других пользователей должны быть недоступны никому, кроме владельца Автомобиля; в настоящее время только программирование в твердой форме не позволяет никому просматривать автомобили других людей! Во-вторых, кажется неаккуратным заботиться о проблеме, модифицируя конструкторы таким образом. Что вы все думаете об этом, и есть ли способ обеспечить это?

1 Ответ

1 голос
/ 04 мая 2010

в первую очередь это должно происходить на уровне, когда вы знаете, кто является текущим пользователем. В Django нет ничего похожего на глобальный request.user, поэтому вам нужно проверить это там, где у вас есть объект запроса, или передать его в качестве параметра.

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

class CarManager(models.Manager):
    def for_user(self, user):
        return super(CarManager, self).get_query_set().filter(creator=user)

Возможно, вы захотите переопределить менеджер по умолчанию, а его методы по умолчанию разрешают только этот метод.

Во второй части вам не нужно изменять конструктор, есть другие способы, если вам это не нравится. Но их изменение гарантирует, что, например, вы не сможете создать форму без зарегистрированного пользователя. Другой способ - использовать ModelChoiceField и переопределить его атрибут набора запросов в представлении:

form.car.queryset = Car.objects.for_user(request.user)

но этот подход подвержен ошибкам. Вам следует изменить конструктор формы следующим образом:

class PartForm(forms.ModelForm):
    def __init__(self,user,*args,**kwargs):
        super (PartForm,self ).__init__(*args,**kwargs)
        self.fields['car'].queryset = Car.objects.for_user(user)

Надеюсь, это поможет.

...