Показ дописів із міткою forms. Показати всі дописи
Показ дописів із міткою forms. Показати всі дописи

зміна queryset в формі

Є три моделі з наступними зв'язками і форма:

class Task(models.Model):
location = models.ForeignKey(Locations, related_name='Task_location')
buyer = models.ForeignKey(UserProfile, related_name='Task_buyer')

class Locations(models.Model):
user = models.ForeignKey('registration.UserProfile', \
verbose_name=_('user'), related_name="user_locations")

class UserProfile(User):

class TaskForm(ModelForm):

class Meta:
model = Task
fields = ('location', 'name', 'description')


Тобто, в таск привязаний до юзера і юзерського локейшена. Форма мені виводить всі локейшени всіх юзерів, що не є добре. Хочу щоб виводились лише рідні локейшени юзера.

Рішення просте. Перевизначити init TaskForm'и і змінити queryset поля location
У вюшці в конструктор TaskForm передаємо request.user, бо нам треба буде фільтрувати по ньому Locations
views.py
@login_required
@render_to('')
def task_add(request, template="tasks/add.html"):
if request.method == 'POST':
form = TaskForm(request.POST, user=request.user)
if form.is_valid():
task = form.save(request.user, 1)
TaskStatus.objects.create(task=task, task_status=1)
return redirect("home")
else:
form = TaskForm(user=request.user)
return {'form': form,}, template

forms.py
class TaskForm(ModelForm):

class Meta:
model = Task
fields = ('category', 'location', 'name', 'description', 'price')

def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(TaskForm, self).__init__(*args, **kwargs)
self.fields['location'].queryset=Locations.objects.filter(user=self.user)

def save(self, user=None, task_status=None, commit=True):
task_object = super(TaskForm, self).save(commit=False)
task_object.buyer = user
task_object.task_status = task_status
if commit:
task_object.save()
return task_object

int значення в radio форму



class ReviewForm(ModelForm):
RATING_CHOICES = ((1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5'),)
rate = forms.TypedChoiceField(choices=RATING_CHOICES, \
widget=forms.RadioSelect, coerce=int)

def clean_rate(self):
if self.cleaned_data['rate'] >= 1 and self.cleaned_data['rate'] <= 5:
return self.cleaned_data['rate']
else:
raise forms.ValidationError(_("Rating error"))

class Meta:
model = Reviews
fields = ('rate', 'message', 'content_type', 'object_id')
widgets = {
'content_type' : forms.HiddenInput(),
'object_id' : forms.HiddenInput()
}

Передавання у формах значень у вигляді hidden полей

Є модель
class Reviews(models.Model):
object_id = models.PositiveIntegerField(_('object id'))
content_type = models.ForeignKey(ContentType, verbose_name=_('content type'))
object = GenericForeignKey('content_type', 'object_id')
rate = models.DecimalField(decimal_places=1, max_digits=2)
user = models.ForeignKey(User, verbose_name=_('user'))
message = models.TextField(_('message'))
timestamp = models.DateTimeField(_('timestamp'), auto_now_add=True)
def __unicode__(self):
return unicode(self.user)

при роботі з формами треба object_id і object_id передавати у hidden полях і також ініціалізувати їх при створенні форми.
forms.py
class ReviewForm(ModelForm):

class Meta:
model = Reviews
fields = ('rate', 'message', 'content_type', 'object_id')
widgets = {
'content_type' : forms.HiddenInput(),
'object_id' : forms.HiddenInput()
}


views.py
    if request.method == "POST":
form = ReviewForm(request.POST)
if form.is_valid():
r = form.save(commit=False)
r.user = request.user
r.save()
return redirect('home')
else:
ct = ContentType.objects.get_for_model(user)
form = ReviewForm(initial={'content_type': ct.pk, 'object_id': user.id})

додавання значення поля форми через перевизначення ModelForm

ситуація наступна: є форма, але передається весь комплект значень окрім task.buyer, який береться з авторизації. Перевизначаємо save, де і зберігаємо task.buyer.
views.py
@render_to('')
def tasks_add(request, template="tasks/add.html"):
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
task = form.save(request.user)
return HttpResponseRedirect('/tasks/details/%s' % task.id)
else:
form = TaskForm()

return {'form': form,}, template

forms.py
class TaskForm(ModelForm):
class Meta:
model = Task
fields = ('name', 'description', 'price',)

def save(self, user=None, commit=True):
task = super(TaskForm, self).save(commit=False)
task.buyer = user
if commit:
task.save()
return task

ініціалізація значення поля форми

для простих речей можна використати initial, наприклад, автозаповнення дати.
Тут трошки інший підхід. Ініціалізація динамічного значення форми на стадії ініціалізації ModelForm
views.py
@render_to("messages/send.html")
def message_send(request, user_id=None):
form = MessageSendForm(message_to='sdsd')
return {"form" : form}

forms.py
class MessageSendForm(forms.ModelForm):
message_to = forms.CharField(label=_("Message to"), max_length=100, required=True)

class Meta:
model = Message
fields = ('message_to','subject','text',)

def __init__(self, *args, **kwargs):
message_to = kwargs.pop('message_to',None)
super(MessageSendForm, self).__init__(*args, **kwargs)
self.fields["message_to"].initial = message_to


На виході маємо:



трошки пізніше покажу наглядний приклад використання цієї конструкції