ModelForm not showing up in Django template? - django

models
class VideoInfo(models.Model):
user = models.ForeignKey(User)
video_name = models.CharField(max_length=200)
director = models.CharField(max_length=200)
cameraman = models.CharField(max_length=200)
editor = models.CharField(max_length=200)
reporter = models.CharField(max_length=200)
tag = models.TextField()
forms
class LoginForm(forms.Form):
username = forms.CharField(max_length=50)
password = forms.CharField(widget=PasswordInput())
class VideoInfoForm(forms.Form):
class Meta:
model = VideoInfo
fields = ['video_type', 'director', 'cameraman', 'editor', 'reporter', 'tag']
Views:
class Main(View):
'''Index page of application'''
def get(self, request):
model = VideoInfo
form = VideoInfoForm()
return render_to_response('main.html', {'form':form}, context_instance=RequestContext(request))
Calling in template as:
{{form.as_p}}
The form is not showing up but if I use LoginForm it's showing up. what am I doing wrong?

Change:
class VideoInfoForm(forms.Form):
To:
class VideoInfoForm(forms.ModelForm):

As you want to use model form, your definition of the form is not correct.
Change
class VideoInfoForm(forms.Form):
to
class VideoInfoForm(forms.ModelForm):
# ------------------^ use ModelForm not Form
Sidenote:
Instead of long list of fields use exclude to just list fields that are not needed.
class VideoInfoForm(forms.ModelForm):
class Meta:
model = VideoInfo
exclude = ['user',]

Related

Getting pk from selected object in a generic ListView html to populate a FK for a new form (CBV)

I'm trying to make a carwash app and I am having issues getting the wash form populated with the vehicle's pk. I've tried with "get_initial", "get_context_data", "form_valid", passing {% url 'appname:urlname' object.pk %} in a html button, even thought about formsets. So if you can guide this noob in polishment (me), I would greeeeaaaatly apreciate it!
so this is what the code is simplified to...
model:
class Car(models.Model):
carplates = models.CharField(max_length=50, unique=True, null=False)
owner = models.ForeignKey(User, on_delete=models.CASCADE, null=False)
class Wash(models.Model):
vehicle_to_wash = models.ForeignKey(Car, on_delete=models.CASCADE)
specific_comment = models.TextField(max_length=500, blank=True, null=True
form:
class WashServiceForm(forms.ModelForm):
class Meta:
model = Wash
fields = ['specific_comment', 'vehicle_to_wash']
views:
class CarList(LoginRequiredMixin, ListView):
model = Car
def get_queryset(self):
return Car.objects.filter(user=self.request.user)
def get_context_data(self, **kwargs):
context = super(CarList, self).get_context_data(**kwargs)
context['car_list'] = context['object_list'].filter(user=self.request.user)
return context
class WashService(LoginRequiredMixin, CreateView):
model = Wash
form_class = WashServiceForm
template_name = 'service_app/standard_wash_form.html'
success_url = reverse_lazy('service_app:wash_review')
class WashReview(LoginRequiredMixin, TemplateView):
model = Wash
urls:
app_name = 'service_app'
urlpatterns = [
path('car-list/', CarList.as_view(), name='car_list'),
path('<int:id>/select_wash/', WashService.as_view(), name='wash_service'),
path('<int:pk>/review', WashReview.as_view(), name='wash_review'),
]
For class based views you can use self.kwargs.get('parameter')
You also need to add get_success_url to your class WashService
class WashService(LoginRequiredMixin, CreateView):
model = Wash
form_class = WashServiceForm
template_name = 'service_app/standard_wash_form.html'
def get_success_url(self):
return reverse('service_app:wash_review',args=[self.object.id])

Filtering foreign key data by created_by field using Class-Based-View

This is my models.py
class InvoiceLine(AbstractSaleLine):
invoice = models.ForeignKey('books.Invoice',
related_name="lines")
name = models.ForeignKey('books.Item')
tax_rate = models.ForeignKey('books.TaxRate')
class Meta:
pass
class Item(models.Model):
item = models.CharField(max_length=255)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="Item", default=1)
views.py
class InvoiceCreateView(generic.CreateView):
template_name = "books/invoice_create_or_update.html"
model = Invoice
form_class = InvoiceForm
formset_class = InvoiceLineFormSet
success_url = reverse_lazy("books:invoice-list")
forms.py
class InvoiceLineForm(RestrictLineFormToOrganizationMixin,
ModelForm):
class Meta:
model = InvoiceLine
fields = (
"name",
"tax_rate",
"item_id"
)
How do i filter Item the foreign key by field created_by using CBV? I am using CreateView.
You can override get_queryset, to get current user use self.request.user. To filter by related model's field use __ notation:
class InvoiceCreateView(generic.CreateView):
template_name = "books/invoice_create_or_update.html"
model = InvoiceLine
form_class = InvoiceForm
formset_class = InvoiceLineFormSet
success_url = reverse_lazy("books:invoice-list")
def get_queryset(self):
return InvoiceLine.objects.filter(name__created_by=self.request.user)
You can override the queryset for the ModelChoiceField when the form is initialised:
class InvoiceLineForm(RestrictLineFormToOrganizationMixin, ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
self.fields['item'].queryset = Item.objects.filter(created_by=user)
class Meta:
model = InvoiceLine
fields = (
"name",
"tax_rate",
"item" # Note this should be `item` not `item_id`
)
You then need to pass the user to the form when you initialise the formset - something like:
formset = formset_class(form_kwargs={'user': self.request.user})

Show model values as multi select options in admin

I am trying to store use the values from two different models to show as choices in form and store them in new model.
Here is what I have now.
models.py
class Employee(models.Model):
name = models.CharField(max_length=200)
class Product(models.Model):
code = models.CharField(primary_key=True, max_length=5)
class JobQueue(models.Model):
emp_name = models.CharField(max_length=200)
product_code = models.CharField(max_length=5)
forms.py
class JobQueueForm(forms.ModelForm):
emp_choices = Employee._meta.get_field('name').choices
product_code_choices = Product._meta.get_field('code').choices
emp_name = forms.ChoiceField(choices = emp_choices)
product_code =forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=product_code_choices)
def save(self, commit=True):
return super(JobQueueForm, self).save(commit = commit)
class Meta:
model = JobQueue
fields = ('emp_name', 'product_code')
admin.py
class JobQueueAdmin(admin.ModelAdmin):
form = JobQueueForm
fieldsets = (
(None,{
'fields': ('emp_name', 'product_code'),}),
)
def save_model(self, request, obj, form, change):
super(JobQueueAdmin, self).save_model(request, obj, form, change)
admin.site.register(models.Employee, AuthorAdmin)
admin.site.register(models.Product, ProductAdmin)
admin.site.register(models.JobQueue, JobQueueAdmin)
I do have values stored in Employee and Product models, but I dont see them as options in JobQueue model in Admin portal.
Am I missing anything here?
emp_choices = Employee._meta.get_field('name').choices
This line doesn't make sense. It tries to get the choices for the Employee.name field, but you did not specify any choices for the name field in your model.
class Employee(models.Model):
name = models.CharField(max_length=200)
If you want generate a list of choices from all the existing employees in the database, then you can define a method that does this:
def get_names():
return Employee.objects.values_list('name', 'name')
Then use this method in your form:
class JobQueueForm(forms.ModelForm):
emp_name = forms.ChoiceField(choices=get_names)
...

Current user as a comment's autor (DJANGO)

I have create a model called 'Comentario' where the logged user can create his own comment. How can I do to automatically save as the author of the comment the logged user. Here I show my schema:
models.py
class Comentario (models.Model):
titulo = models.CharField(max_length=50)
texto = models.CharField(max_length=200)
autor = models.ForeignKey (Perfil, editable=False, blank=True)
fecha_publicacion = models.DateTimeField(auto_now_add=True)
tag = models.ManyToManyField(Tags, blank=True)
def __str__(self):
return (self.titulo)
views.py
class ComentarioCreate (LoginRequiredMixin,CreateView):
model = Comentario
form_class = ComentarioForm
template_name = 'home/comentario_form.html'
success_url = reverse_lazy ('home:listar')
def save(self):
autor=self.request.user.username
user.save()
forms.py
class ComentarioForm(forms.ModelForm):
class Meta:
model = Comentario
fields = [
'titulo',
'texto',
'tag',
]
labels = {
'titulo': 'Titulo',
'texto' : 'Descripcion',
'tag' : 'Etiquetas',
}
widgets = {
'titulo':forms.TextInput(attrs={'class':'form-control'}),
'texto':forms.TextInput(attrs={'class':'form-control'}),
'tag':forms.CheckboxSelectMultiple(),
}
Perfil is a model which inherits form AbstractUser.
models.py
class Perfil(AbstractUser):
nom_puesto = models.ForeignKey(Puesto, blank = True)
def __str__(self):
return '{}'.format(self.username)
How can I do to have in the field 'autor' the username of the logged user?
thank you for your answer!
The method to override is form_valid, not save; see models and request.user which explains exactly what to do.

Limit choices to foreignkey in django rest framework

How to limit images of request.user to be linked with node. I wish I could do something like:
photo = models.ForeignKey(
Image,
limit_choices_to={'owner': username},
)
but request.user rather than username and I don't want to use local threads.
models.py
class Node(models.Model):
owner = models.ForeignKey(User)
content = models.TextField()
photo = models.ForeignKey(Image)
class Image(models.Model):
owner = models.ForeignKey(User)
file = models.ImageField(upload_to=get_upload_file_name)
serializers.py
class ImageSerializer(serializers.ModelSerializer):
owner = serializers.Field('owner.username')
class Meta:
model = Image
fields = ('file', 'owner')
class NodeSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Node
fields = ('content', 'photo', 'owner')
I would deal with this by overriding get_serializer_class to dynamically return a serializer class at runtime, setting the choices option on the field there:
def get_serializer_class(self, ...):
user = self.request.user
owner_choices = ... # However you want to restrict the choices
class ImageSerializer(serializers.ModelSerializer):
owner = serializers.Field('owner.username', choices=owner_choices)
class Meta:
model = Image
fields = ('file', 'owner')
return ImageSerializer
You can create a custom foreign key field and define get_queryset() method there to filter related objects to only those of your user. The current user can be retrieved from the request in the context:
class UserPhotoForeignKey(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
return Image.objects.filter(owner=self.context['request'].user)
class NodeSerializer(serializers.HyperlinkedModelSerializer):
photo = UserPhotoForeignKey()
class Meta:
model = Node
fields = ('content', 'photo', 'owner')
This example is using Django REST Framework version 3.
class CustomForeignKey(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
return Table.objects.filter(is_active=True)
class Serializer(serializers.ModelSerializer):
(...)
table= CustomForeignKey()
class Meta:
(...)
even more easy is :
class Serializer(serializers.ModelSerializer):
(...)
table = serializers.PrimaryKeyRelatedField(queryset=Table.objects.filter(is_active=True))
class Meta:
(...)
Because I am sure this logic will be used across an entire Django application why not make it more generic?
class YourPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
def __init__(self, **kwargs):
self.model = kwargs.pop('model')
assert hasattr(self.model, 'owner')
super().__init__(**kwargs)
def get_queryset(self):
return self.model.objects.filter(owner=self.context['request'].user)
serializers.py
class SomeModelSerializersWithABunchOfOwners(serializers.ModelSerializer):
photo = YourPrimaryKeyRelatedField(model=Photo)
categories = YourPrimaryKeyRelatedField(model=Category,
many=True)
# ...
from rest_framework import serializers
class CustomForeignKey(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
return Table.objects.filter(user=self.context['request'].user)
# or: ...objects.filter(user=serializers.CurrentUserDefault()(self))
class Serializer(serializers.ModelSerializer):
table = CustomForeignKey()