How do I write a form in django - python

I am writing a forums app for my final project in class and I am trying to write a form for creating a new thread, Basically all I need it to do is
username: text box here
Name of thread: Text box here
Post: text box here
I want to do this in forms.py instead of making a template for it.
url(r"^(.+)/new_thread/$", new_thread, name="thread_new_thread"),
That's my url thread
def list_threads(request, forum_slug):
"""Listing of threads in a forum."""
threads = Thread.objects.filter(forum__slug=forum_slug).order_by("-created")
threads = mk_paginator(request, threads, 20)
template_data = {'threads': threads, 'forum_slug': forum_slug}
return render_to_response("forum/list_threads.html", template_data, context_instance=RequestContext(request))
That is my list_threads view, I have a button that should link to the forms.py version of my new thread post
class Thread(models.Model):
title = models.CharField(max_length=60)
slug = models.SlugField(max_length=60)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
forum = models.ForeignKey(Forum)
class Meta:
unique_together = ('slug', 'forum', )
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Thread, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('forum_list_posts', args=[self.forum.slug, self.slug])
def __unicode__(self):
return unicode(self.creator) + " - " + self.title
def num_posts(self):
return self.post_set.count()
def num_replies(self):
return self.post_set.count() - 1
def last_post(self):
if self.post_set.count():
return self.post_set.order_by("created")[0]
This is my thread model
Any suggestions?

Read the documentation:
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/
I guess that the Thread has a model.
class ThreadForm(ModelForm):
def __init__(self, forum, user, *args, **kwargs):
super(ThreadForm, self).__init__(*args, **kwargs)
self.forum = forum
self.user = user
def save(self):
thread = super(ThreadForm, self).save(commit=False)
thread.forum = self.forum
thread.creator = self.user
thread.save()
return thread
class Meta:
model = Thread
exclude = ('slug', 'created', 'creator', 'forum')
In your views:
def thread_add(self, forum_id):
data = None
if request.method == 'POST':
data = request.POST
forum = Forum.objects.get(id=form_id)
form = ThreadForm(forum=forum, user=request.user, data=data)
if form.is_valid():
form.save()
.............
return render_to_response .....
In your model left a field to "Post: text box here"

Related

Django createView passing current user_id to Modelform

I am trying to make a calendar app and currently trying to stop people from being about to save an event when they are already busy during that time period. I believe my issue is that the modelForm doesn't have the user_id as part of the form object. how can I pass the user_id so I can use it to filter with the clean().
I tried using get_form_kwargs() but this doesn't seem to be the correct route to take.
Please can you point me in the right direction of how to do this.
view.py
class CalendarEventAdd(LoginRequiredMixin, CreateView):
model = Event
form_class = EventForm
template_name = 'calendar_create_event_form.html'
success_url = reverse_lazy('calendar_list')
def form_valid(self, form):
form.instance.manage = self.request.user
return super(CalendarEventAdd, self).form_valid(form)
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(CalendarEventAdd, self).get_form_kwargs()
kwargs['user_id'] = self.request.user
return kwargs
form.py
class EventForm(forms.ModelForm):
class Meta:
model = Event
widgets = {
'start_time': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
'end_time': DateInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M'),
}
fields = ['avilibility','start_time','end_time']
def __init__(self, *args, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
# input_formats parses HTML5 datetime-local input to datetime field
self.fields['start_time'].input_formats = ('%Y-%m-%dT%H:%M',)
self.fields['end_time'].input_formats = ('%Y-%m-%dT%H:%M',)
def clean(self, *args, **kwargs):
form_start_time = self.cleaned_data.get('start_time')
form_end_time = self.cleaned_data.get('end_time')
form_manage_id = self.cleaned_data.get('manage_id')
between = Event.objects.filter(manage_id=1, end_time__gte=form_start_time, start_time__lte=form_end_time)
if between:
raise forms.ValidationError('Already Calendar entry for this time')
super().clean()
model.py
class Event(models.Model):
avilibility_choices = [
('Avilible', 'Avilible'),
('Busy', 'Busy'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
manage = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
avilibility = models.CharField(max_length=10, choices=avilibility_choices, editable=True)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
def __str__(self):
return self.avilibility + " - " + str(self.start_time) + " - " + str(self.end_time) + " - " +str(self.id)
def get_absolute_url(self):
return reverse('calendar_event_detail', args=[str(self.id)])
def get_absolute_url_edit(self):
return reverse('calendar_event_detail_update', args=[str(self.id)])
def get_html_url(self):
url = reverse('event_edit', args=(self.id,))
return f' {self.avilibility} '
In your view, you should pass the primary key of the user, so:
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(CalendarEventAdd, self).get_form_kwargs()
kwargs['user_id'] = self.request.user.pk
return kwargs
You can save it in the EventForm object:
class EventForm(forms.ModelForm):
def __init__(self, *args, user_id=None, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
self.user_id = user_id
# input_formats parses HTML5 datetime-local input to datetime field
self.fields['start_time'].input_formats = ('%Y-%m-%dT%H:%M',)
self.fields['end_time'].input_formats = ('%Y-%m-%dT%H:%M',)
def clean(self, *args, **kwargs):
form_start_time = self.cleaned_data.get('start_time')
form_end_time = self.cleaned_data.get('end_time')
form_manage_id = self.cleaned_data.get('manage_id')
between = Event.objects.exclude(pk=self.instance.pk).filter(
manage_id=self.user_id,
end_time__gte=form_start_time,
start_time__lte=form_end_time
)
if between.exists():
raise forms.ValidationError('Already Calendar entry for this time')
return super().clean()
The .exclude(pk=self.instance.pk) will exclude the object you are editing, if you later decide to use the EventForm not only to create but also update an Event object.
Note: The documentation advises to
use the AUTH_USER_MODEL setting [Django-doc] over
get_user_model() [Django-doc].
This is safer, since if the authentication app is not yet loaded, the settings
can still specify the name of the model. Therefore it is better to write:
from django.conf import settings
class Event(models.Model):
# …
manage = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)

not working update method in rest API framework

I want to be able to edit registered User profile by using UpdateModelMixin class. The forms to edit is existed but when we want to PUT the new information , the new one is not applied and the pervious info is displayed.
models.py:
class Student(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
entry_year = models.PositiveIntegerField()
student_no = models.PositiveIntegerField()
def get_full_name(self):
return self.user.first_name + self.user.last_name
def __unicode__(self):
return self.get_full_name()
views.py:
class ProfessorDetailAPIView(DestroyModelMixin, UpdateModelMixin, RetrieveAPIView):
queryset = Professor.objects.all()
serializer_class = ProfessorDetailSerializers
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
serializers.py:
class ProfessorDetailSerializers(serializers.ModelSerializer):
user = CustomUserSerializer()
professor_no = SerializerMethodField()
class Meta:
model = Student
fields = (
'user',
'professor_no',
)
def get_professor_no(self, obj):
return str(obj.professor_no)
There is not any changes applied on information

Why my edit form not updating data, but able to create new instance. I try every thing on google but still not working

I have a form for creating the object, and it works fine. When I use that form for editing the object, it doesn't work. I did debugging the post method,and it also works fine, the form is valid, the redirect work, the success message appear, but not update the object. The form instance is also work correctly. It just don't update
# models.py
class Item(models.Model):
status_choices = (
('rent','Rent'),
('give', 'Give'),
('share','Share'),
)
item_types = (
('book','Book'),
('movie','Movie',),
('data','Data'),
('other','Other'),
)
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, blank=True,unique=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
cover = models.ImageField(upload_to='items/%Y/%m/%d',blank=True)
link = models.URLField(blank=True)
description = models.TextField(max_length=500, blank=True)
status = models.CharField(max_length=10,choices=status_choices,default='Share')
item = models.CharField(max_length=10, choices=item_types,default='Data', verbose_name='Item Type')
publish = models.DateTimeField(auto_now=True,null=True)
class Meta:
ordering = ('-publish',)
index_together = (('id', 'slug'),)
def __str__(self):
return '{} : <{}> for {}'.format(self.title,self.item,self.status)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('item_edit', kwargs={'slug':self.slug})
#forms.py
class ItemShareForm(forms.ModelForm):
class Meta:
model = Item
fields = ('title', 'cover', 'link', 'description', 'status', 'item')
widgets = {
'description' : forms.Textarea(),
}
#views.py
#login_required
def item_edit(request,slug):
instance = get_object_or_404(Item,slug=slug)
if request.method == 'POST': #check the request method
edit_form = ItemShareForm(request.POST ,instance=instance)
if edit_form.is_valid(): # check the form validation
update_item = edit_form.save(commit=False)
update_item.owner = request.user #assign the owner
update_item.save() # update the instance
messages.success(request,'Your item has been updated successfully') # writing the message to user
return redirect('/')
else:
messages.error(request,'Error updating your item...')
else:
edit_form = ItemShareForm(instance=instance)
return render(request, 'account/share.html',{'itemform':edit_form})*
You have overridden you model save method like so:
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)
This means that the object will only ever get saved if the slug is empty - i.e., it will only ever get saved once. Any future calls to save will not execute that if block, and nothing will happen.
You probably mean to do this instead - note indentation of the last line:
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)

submit form as superuser vs regular user

In my django app I have a Myuser(User) class. It inherits the User class.
When a new user is created the Myuser table is poplulated.
myusers.py
class Myuser(User):
address = models.CharField(max_length=40)
pobox = models.CharField(max_length=40)
models.py
class Someclass(models.Model):
objectid = models.IntegerField()
objecttype = models.CharField(max_length=200)
created = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(auto_now=True)
class Someotherclass(Someclass):
status = models.IntegerField(default=0,)
name = models.CharField(max_length=200)
created = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User)
forms.py
class SomeotherclassForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
self.user = kwargs.pop('user')
self.app = kwargs.pop('app')
self.table = kwargs.pop('table')
self.mytype = kwargs.pop('mytype')
initial = kwargs.get('initial', {})
super(SomeotherclassForm, self).__init__(*args, **kwargs)
create.py
class DataCreate(CreateView):
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
#some code here not relevant at all
def get_form_kwargs(self):
kwargs = super(DataCreate, self).get_form_kwargs()
objectid = self.request.GET.get('objectid',None)
objecttype = self.request.GET.get('objecttype',None)
kwargs.update({'mytype': objecttype})
kwargs.update({'request': self.request})
kwargs.update({'user': self.request.user})
kwargs.update({'app': self.app})
kwargs.update({'table': self.kwargs['table'].lower()})
return kwargs
def form_valid(self, form):
obj = form.save(commit=False)
group = ''
if not self.request.user.is_superuser:
group = MyUser.objects.get(user_ptr_id=self.request.user.pk)
else:
groups = self.request.user.groups.all()
if self.kwargs['table'] == 'Myprotocol':
obj = form.save(commit=False)
table = eval(self.request.GET.get('objecttype',None).title()).objects.get(pk=int(self.request.GET.get('objectid',None)))
obj.objectid = table.pk
obj.objecttype = table.__class__.__name__.lower()
obj.user_id = self.request.user.pk
obj.save()
else:
obj = form.save()
if self.request.POST.get('is_popup'):
check = int(self.kwargs['is_list'])
if self.kwargs['table'] == 'Someclass':
popup = 1
a = checkPopup2(obj,check,popup,obj.pk)
else:
a = checkPopup(obj,check)
return a
else:
return super(DataCreate, self).form_valid(form)
When I have logged in as a regular user ,everything works fine.
When I log in as a superuser, I get form error that objecttype,objectid and user are not filled.
In my attempts to troubleshoot it , I realized that when I am logged in as a superuser ,it dowsn't reach the form_valid() function.
I can't figure out why that is happening.
Any suggestions or advice on how to troubleshoot it?

Django: Use post() in UpdateView to populate form's fields with instance's existing field values

I have trouble getting the current instance's fields on my UpdateView. How do I get the specific instance based on its id?
views.py
class ShowUpdate(UpdateView):
model = Show
fields = ['description', 'season', 'episode']
def post(self, request, **kwargs):
request.POST = request.POST.copy()
request.POST['description'] = "how to get instance description?" # problem here
request.POST['season'] = 2
return super(ShowUpdate, self).post(request, **kwargs)
models.py
class Show(models.Model):
owner = models.ForeignKey(User, null=True, default=True, related_name='o')
title = models.CharField(max_length=100)
description = models.TextField(default='N/A', blank=True, max_length=250)
season = models.IntegerField(default=0)
episode = models.IntegerField(default=0)
def get_absolute_url(self):
return reverse('show:index')
def __str__(self):
return self.title
Look to the UpdateView docs
This View has method get_object(self, queryset=None)
In you case just need to call it in POST method something like this:
class ShowUpdate(UpdateView):
model = Show
fields = ['description', 'season', 'episode']
def post(self, request, **kwargs):
self.object = self.get_object()
request.POST = request.POST.copy()
request.POST['description'] = self.object.description
request.POST['season'] = 2
return super(ShowUpdate, self).post(request, **kwargs)

Categories

Resources