Django CreateView Model Form not uploading File - django

the problem that I have is that my Model Form is not uploading a file, I had it working and after adding more code now is not working, this is what it happens: It uploads/save all the other fields except for the file, the strange thing is that if I do it from the admin site it does work. I will add that is not writing the path in the database column.
models.py
class Polizas(models.Model):
nombre = models.CharField(max_length=30, blank=True, null=True)
numero = models.CharField(max_length=30, unique=True)
aseguradora = models.CharField(max_length=20, blank=True, null=True)
carro = models.ForeignKey(
Carros, on_delete=models.CASCADE, blank=True, null=True)
inicio_poliza = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
fin_poliza = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
documento = models.FileField(upload_to='polizas/', blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Polizas"
ordering = ['nombre']
def __str__(self):
return self.nombre
def get_absolute_url(self):
return reverse('polizas')
forms.py
class PostPolizas(forms.ModelForm):
class Meta:
model = Polizas
fields = ('nombre', 'numero', 'aseguradora', 'carro', 'inicio_poliza',
'fin_poliza', 'documento')
widgets = {'inicio_poliza': forms.DateInput(attrs={'type': 'date'}),
'fin_poliza': forms.DateInput(attrs={'type': 'date'})
}
views.py
class PolizaCreate(LoginRequiredMixin, CreateView):
login_url = '/login/'
redirect_field_name = 'redirect_to'
form_class = PostPolizas
template_name = "add_insurance.html"
Terminal
[06/May/2020 22:32:17] "POST /insurance/add/ HTTP/1.1" 200 4557
[06/May/2020 22:32:25] "POST /insurance/add/ HTTP/1.1" 302 0
I have tried to validate the form and it is not working, this is error is happening in my other model forms that upload files, it uploads the text fields and dates but not the files.

Try adding enctype="multipart/form-data" like this:
<form enctype="multipart/form-data" method="post">
{% csrf_token%}
<table> {{form}} </table>
<input type="submit" value="Post">
</form>
in the template form.

By default forms only pass request.POST since you are uploading a file you have to pass request.FILES into the form's constructor
Follow: https://docs.djangoproject.com/en/2.2/topics/http/file-uploads/

Related

django filters form not showing

django filters form not showing
it is supposed to show a form but only shows the submit button
models.py:
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,null=True)
bio = models.TextField()
phone_number = models.IntegerField(blank=True, null=True)
Birth_date = models.DateField(blank=True, null=True)
age = models.IntegerField(blank=True, null=True)
education = models.TextField(blank=True, null=True,max_length=45)
WorkType = models.CharField(blank=True, null=True,max_length=150)
desired_wage = models.IntegerField(blank=True, null=True)
location = models.CharField(blank=True, null=True,max_length=25)
gender = models.PositiveSmallIntegerField(blank=True, null=True,choices=GENDER_CHOICES)
def __str__(self):
return str(self.user) if self.user else ''
views:
def ListingsPage(request):
Profile = Profile.objects.all()
profile_filter = ProfileFilter(request.GET,queryset=Profile)
profile = profile_filter.qs
context = {
"filter":profile_filter,
"profile":Profile,
}
return render(request,"base/Listings.html",context)
filters.py:
import django_filters
from .models import Profile
class ProfileFilter(django_filters.FilterSet):
class Meta:
model = Profile
fields = ['bio','location']
tempmlate:
<div>
<form method="GET" action="{% url 'listings' %}">
{{filter.form}}
<button type="submit" value="Submit">Submit</button>
</form>
</div>
It's supposed to show a form, it doesn't
You have typo mistake in profile queryset like this...
you need to write Profile instead of profile
def ListingsPage(request):
Profile = Profile.objects.all()
profile_filter = ProfileFilter(request.GET,queryset=Profile)
Profile = profile_filter.qs # <--------- this correction need
context = {
"filter":profile_filter,
"profile":Profile,
}
return render(request,"base/Listings.html",context)

Django how to generate a filtered queryset

I have got 2 models. Asset and Asset_Type. In my asset_type detail view i would like to list all assets of that asset type. I think I have to use models.Asset.queryset().filter() but i can't get it to work.
On my template I would like to loop though the list with a 'for' (example: object in list) and print the values like this {{ object.name }}
models.py
class Asset(models.Model):
# Relationships
room = models.ForeignKey("asset_app.Room", on_delete=models.SET_NULL, blank=True, null=True)
model_hardware = models.ForeignKey("asset_app.Model_hardware", on_delete=models.SET_NULL, blank=True, null=True)
# Fields
name = models.CharField(max_length=30)
serial = models.CharField(max_length=30, unique=True, blank=True, null=True, default=None)
mac_address = models.CharField(max_length=30, null=True, blank=True)
purchased_date = models.DateField(null=True, blank=True)
may_be_loaned = models.BooleanField(default=False, blank=True, null=True)
notes = models.TextField(max_length=448, null=True, blank=True)
ip = models.CharField(max_length=90, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name)
def get_absolute_url(self):
return reverse("asset_app_asset_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_asset_update", args=(self.pk,))
class Asset_type(models.Model):
# Fields
name = models.CharField(max_length=30)
last_updated = models.DateTimeField(auto_now=True, editable=False)
created = models.DateTimeField(auto_now_add=True, editable=False)
notes = models.TextField(max_length=448, null=True, blank=True)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name)
def get_absolute_url(self):
return reverse("asset_app_asset_type_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_asset_type_update", args=(self.pk,))
class Model_hardware(models.Model):
# Relationships
asset_type = models.ForeignKey("asset_app.Asset_type", on_delete=models.SET_NULL, blank=True, null=True)
brand = models.ForeignKey("asset_app.Brand", on_delete=models.SET_NULL, blank=True, null=True)
# Fields
name = models.CharField(max_length=30)
notes = models.TextField(max_length=448, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name) + " :: " + str(self.brand.name) + " :: " + self.asset_type.name
def get_absolute_url(self):
return reverse("asset_app_model_hardware_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_model_hardware_update", args=(self.pk,))
views.py
class Asset_typeDetailView(generic.DetailView):
model = models.Asset_type
form_class = forms.Asset_typeForm
You can simply iterate over the related objects in the template by using the default related name which is the model name in lowercase with _set appended. So asset_type.model_hardware_set.all() will give you all Model_hardware instances related to Asset_type and similarly for model_hardware.asset_set.all():
{% for model_hardware object.model_hardware_set.all %}
{% for asset in model_hardware.asset_set.all %}
{{ asset.name }}
{% endfor %}
{% endfor %}
But this can become slow, since we run into the N + 1 problem that is for each model hardware we will be making queries to get it's assets. We can use prefetch_related_objects on your model instance to prefetch all the related objects (in fewer queries) this and make it faster:
from django.db.models import prefetch_related_objects
from django.views.generic import DetailView
class YourDetailView(DetailView):
model = Asset_type
template_name = '<your_template_name>.html'
def get_object(self, queryset=None):
obj = super().get_object(queryset=queryset)
prefetch_related_objects([obj], 'model_hardware__asset')
return obj
Note: Class names in python should ideally be in PascalCase not Some_case (Don't think there is any such convention as you make
here), hence ModelHardware instead of Model_hardware and
AssetType instead of Asset_type would be better names.

Django import export has error "Tablib has no format 'None' or it is not registered"

I am trying to implement csv import in my application and I have this error,
Tablib has no format 'None' or it is not registered.
I am using python 3.5 and Django 2.2.
I tried the same code with python 2.7 with Django 1.8 and it worked well. Is there any problem with my code?
My model:
class Stock(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True)
item_name = models.CharField(max_length=50, blank=True, null=True)
quantity = models.IntegerField(default='0', blank=False, null=True)
receive_quantity = models.IntegerField(default='0', blank=True, null=True)
receive_by = models.CharField(max_length=50, blank=True, null=True)
issue_quantity = models.IntegerField(default='0', blank=True, null=True)
issue_by = models.CharField(max_length=50, blank=True, null=True)
issue_to = models.CharField(max_length=50, blank=True, null=True)
phone_number = models.CharField(max_length=50, blank=True, null=True)
created_by = models.CharField(max_length=50, blank=True, null=True)
reorder_level = models.IntegerField(default='0', blank=True, null=True)
last_updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return self.item_name
Resources.py
from import_export import resources
from .models import Stock, Person
class StockResource(resources.ModelResource):
class Meta:
model = Stock
Views.py:
from .resources import StockResource
def upload(request):
if request.method == 'POST':
stock_resource = StockResource()
dataset = Dataset()
new_stock = request.FILES['myfile']
imported_data = dataset.load(new_stock.read())
result = stock_resource.import_data(dataset, dry_run=True) # Test data import
if not result.has_errors():
stock_resource.import_data(dataset, dry_run=False) # Run import
return render(request, 'csv_import.html')
csv_import.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="myfile"><br><br>
<button type="submit">Upload</button>
</form>
csv_import.csv
1,phone,1,0,9,0,9,9,9,,ssaine,0,2020-06-11,
2,computer,2,0,9,0,9,9,9,9,ssaine,0,2020-08-11,
A couple of things to try:
imported_data = Dataset().load(new_stock.read().decode(), format='csv', headers=False)
print(imported_data)
If that doesn't work, verify exactly what is being returned from new_stock.read(). Is it valid csv data? You can test this out locally before you test on the server.
for those that have headers, leave the headers option out and let django pick the headers itself, also it solves the issue of not saving to the database simplyvic raised. so use
imported_data = Dataset().load(new_stock.read().decode(), format='csv')
Dont't forget to install django-import-export module and include app "import-export" in settings, installed apps.

Select a model instance from HTML form on Django

I am trying to get my html form to allow me to pass the company model instance. As of now, I can pull the names of each company instance, however, what would I put into the value attibute of the option field to have it select the instance correctly?
<option value="what to put here?">{{Company.name}}</option>
I was hoping to do this through HTML forms and not Django forms as I have used AJAX to make a nice little live-updating interface.
models.py
class Company(models.Model):
name = models.CharField(max_length=30, null=True, blank=True)
email = models.CharField(max_length=40, null=True, blank=True)
phone = models.CharField(max_length=15, null=True, blank=True)
address = models.CharField(max_length=100, null=True, blank=True)
notes = models.CharField(max_length=400, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, blank=True)
updated = models.DateTimeField(auto_now=True, blank=True)
class Meta:
ordering = ["name"]
def __str__(self):
return self.name
class Contact(models.Model):
firstname = models.CharField(max_length=20, null=True, blank=True)
lastname = models.CharField(max_length=20, null=True, blank=True)
email = models.CharField(max_length=40, null=True, blank=True)
phone = models.CharField(max_length=15, null=True, blank=True)
title = models.CharField(max_length=20, null=True, blank=True)
notes = models.CharField(max_length=400, null=True, blank=True)
company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["lastname"]
def __str__(self):
return self.firstname
views.py
class contact_manager(ListView):
template_name = 'crm/contact_manager.html'
context_object_name = 'contact_manager'
queryset = Contact.objects.all()
def get_context_data(self, **kwargs):
context = super(contact_manager, self).get_context_data(**kwargs)
context['contact'] = Contact.objects.all()
context['company_list'] = Company.objects.all()
# And so on for more models
return context
contact_manager.html
<div class="form-group">
<select class="form-control" name="company" placeholder="Company">
<option value="">Please select a company</option>
{% for Company in company_list %}
<option value="{{Company.name}}">{{Company.name}}</option>
{% endfor %}
</select>
</div>
If you are looking for a unqiue identifier for each option, that links to a model instance on the backend, that is what the ID field is for (Company.id):
<option value="{{ Company.id }}">{{Company.name}}</option>
Then on the backend you can retrieve the model with the posted id:
Company.get(id=posted_id)
Note: id is by default added to your model as the primary key and is a auto incrememting integer.

How to save parent objects within the form_valid

I have a class based view. I am trying to save an object with it's association. I have the following error :
NOT NULL constraint failed: boxes_suggestion.box_id
More explanation: I have a SuggestionBox (Model) and each Participant could add Comments into it. it's sort of a doodle clone.
detail.html
<h3>{{box.title}}</h3>
<form action="." method="post">{% csrf_token %}
{{ form.as_p }}
<input id="box_id_value" type="hidden" name="box_id_value" value='{{box.id}}' />
<input type="submit" class="btn btn-info" value="Add suggies 1" />
</form>
views.py
class SuggiesForm(FormView):
'''
Display the form
Otherwise
Process the form
1-Get the suggestion_box_id
2-Save the comment associated with that suggestion box.
'''
template_name = 'boxes/detail.html'
form_class = SuggestionForm
success_url = '/boxes/success'
box_instance = ''
def get_context_data(self, **kwargs):
'''
Retrieve the id of the Suggestion Box
'''
context = super(SuggiesForm, self).get_context_data(**kwargs)
#Find The appropriate Box so that user can add Suggies
context['box'] = Box.objects.get(pk=self.kwargs['pk'])
box_instance = context['box']
return context
def form_valid(self, form):
'''
'''
form.save(commit=False)
#box = box_instance
form.box = Box.objects.first()
form.participant = Suggestion.objects.first()
form.save()
return super(SuggiesForm, self).form_valid(form)
models.py
#python_2_unicode_compatible
class Box(models.Model):
"""
Box model
"""
def __str__(self):
return self.title
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=40, blank=True, null=True)
identify = models.BooleanField(default=False)
activate = models.BooleanField(default=False)
created_at = models.DateField(auto_now_add=True)
updated_at = models.DateField(auto_now=True)
#expiration_date = models.DateField(auto=Date in Future, blank=True, null=False)
#slug = AutoSlugField(_('slug'), populate_from="id")
#url(slug)
#python_2_unicode_compatible
class Participant(models.Model):
"""
Participant Model
"""
def __str__(self):
return self.email
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(blank=True, null=True, default='anonymous#email.com')
username = models.CharField(max_length=40, blank=True, null=True)
box = models.ForeignKey(Box, on_delete=models.CASCADE)
created_at = models.DateField(auto_now_add=True)
updated_at = models.DateField(auto_now=True)
#python_2_unicode_compatible
class Suggestion(models.Model):
"""
For adding comments (or suggestions)
"""
def __str__(self):
return self.comment[0:10]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
comment = models.CharField("",max_length=250, blank=True, null=True)
box = models.ForeignKey(Participant, on_delete=models.CASCADE)
created_at = models.DateField(auto_now_add=True)
updated_at = models.DateField(auto_now=True)
You correctly used commit=False, but then added the attributes onto the form object itself instead of the object returned from the save. It should be:
object = form.save(commit=False)
object.box = Box.objects.first()
object.participant = Suggestion.objects.first()
object.save()