models.py
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
age = models.IntegerField()
def __unicode__(self):
return "{0} {1} {2} {3} {4}".format(
self, self.first_name, self.last_name, self.email, self.age)
class Book(models.Model):
book_name=models.CharField(max_length=30)
publisher_name=models.CharField(max_length=40)
author=models.ForeignKey(Author)
def __unicode__(self):
return "{0} {1} {2}".format(
self.pk, self.book_name, self.publisher_name)
forms.py
class AuthorForm(ModelForm):
class Meta:
model = Author
BookFormset = inlineformset_factory(Author, Book,
fields=('book_name', 'publisher_name'), extra=1,
can_delete=False)
urls.py is
admin.autodiscover()
urlpatterns = patterns('',
url('^$', index),
url('^index/$', index),
url('^addbook/$', addbook),
url('^book_detail/$', book_detail, 'book_summary'),
url('^editbook/(?P<book_id>\d+)/$', editbook) ,
url('^deletebook/(?P<book_id>\d+)/$',deletebook) ,
url(r'^admin/', include(admin.site.urls)),
)
I need to perform edit and update the row in database,i did it by using single table.But using two table have some confusion how to take 2nd table using that particular id.I am using forms in this.Can you help me in this to write codes in views.py.Example for doing the same using two table is no where i seen.
Thanks
def update_book(request, book_id):
author = get_object_or_404(Author, pk=author_id)
form = AuthorForm(instance=author)
book_formset = BookFormset(instance=author)
if request.method == 'POST':
form = AuthorForm(request.POST, instance=author)
if form.is_valid():
author = form.save(commit=False)
book_formset = BookFormset(request.POST, instance=author)
if book_formset.is_valid():
author.save()
book_formset.save()
return redirect('/index/')
return render_to_response('updatebook.html',{
'form': form, 'formset': book_formset
},context_instance=RequestContext(request))
<div align="center">
<tr>
<form method="POST">
{% csrf_token %}
<h5>Author:</h5>
{{ form.as_p }}
<h5>Book:</h5>
{{ formset.as_p }}
<input type="submit" value="submit">
</form>
</tr>
</div>
Related
I try to add a form-control class to an input field of a model-based form in Django, but I get this error message:
AttributeError: 'CharField' object has no attribute 'use_required_attribute'.
How do I fix this?
class in views.py:
class TweetCreate(LoginRequiredMixin, CreateView):
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
def get_form(self):
form = super().get_form()
form.fields['search_term'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'}))
form.fields['query_type'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'}))
form.fields['start_date'].widget = DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['end_date'].widget = DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['language'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'})),
form.fields['country'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'})),
return form
class in models.py:
class TweetSearch(models.Model):
from datetime import datetime, timedelta
search_term = models.CharField(max_length=200, default='blue bird')
QUERY_CHOICES = (
('t', 'in tweet'),
('h', 'in hashtag'),
('u', 'username'),
)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, blank=True)
query_type = models.CharField(max_length=1, choices=QUERY_CHOICES, blank=True, default='t')
start_default = datetime.now() - timedelta(days=30)
start_date = models.DateTimeField(default=start_default)
end_date = models.DateTimeField(default=datetime.now)
language = models.CharField(max_length=200, default='English')
country = models.CharField(max_length=200, default='USA')
searcher = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
def get_absolute_url(self):
return reverse('tweet_detail', kwargs={'pk': self.pk})
def __str__(self):
return f"Tweets with the word {self.search_term} from {self.start_date} till {self.end_date} written in " \
f"{self.language} in {self.country}."
HTML:
<div class="container" id="searchcontainer" style="text-align: center">
<form action="" method="POST">
{% csrf_token %}
{{form.search_term}}
{{form.query_type}}
{{form.start_date}}
{{form.end_date}}
{{form.language}}
{{form.country}}
<input class="btn btn-primary" type="submit">
</form>
</div>
You are confusing form field with widgets. You should assign a widget like TextInput, not a form field like CharField, like:
class TweetCreateView(LoginRequiredMixin, CreateView):
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
def get_form(self):
form = super().get_form()
form.fields['search_term'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['query_type'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['start_date'].widget=DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['end_date'].widget=DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['language'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['country'].widget=forms.TextInput(attrs={'class': 'form-control'})
return form
It however here might be better to just plug in a ModelForm, so:
class TweetForm(forms.ModelForm):
class Meta:
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
widgets = {
'search_term': forms.TextInput(attrs={'class': 'form-control'}),
'query_type': forms.TextInput(attrs={'class': 'form-control'}),
'start_date': DateTimePickerInput(attrs={'class': 'form-control'}),
'end_date': DateTimePickerInput(attrs={'class': 'form-control'}),
'language': forms.TextInput(attrs={'class': 'form-control'}),
'country': forms.TextInput(attrs={'class': 'form-control'}),
}
and plug this into the TweetCreateView:
class TweetCreateView(LoginRequiredMixin, CreateView):
model = TweetSearch
form_class = TweetForm
if you however only want to change the class, you can simplify this with:
class FormControlForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
class TweetForm(FormControlForm, forms.ModelForm):
class Meta:
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
I am very new in django.
Situation is like this
I have a model
class Slotmodels (models.Model):
modelid = models.AutoField(primary_key=True)
model_desc = models.TextField()
categoryid = models.ForeignKey(categories, on_delete=models.CASCADE)
shopid = models.ForeignKey(shops, on_delete=models.CASCADE)
brandid = models.ForeignKey(brands, on_delete=models.CASCADE)
reference = models.CharField(max_length=50,null=True)
history = models.TextField(null=True)
year = models.IntegerField(null=True)
purchase_price = models.FloatField(default=0)
actual_price = models.FloatField(default=0)
limited_edition = models.BooleanField(null=False,default=False)
color = models.CharField(max_length=50,null=True)
number = models.IntegerField(null=True)
livery = models.CharField(max_length=50,null=True)
sponsor = models.CharField(max_length=50,null=True)
scale = models.CharField(max_length=10,null=True)
engine = models.CharField(max_length=20,null=True)
eng_position = models.CharField(max_length=20,null=True)
crown = models.IntegerField(null=True)
pinion = models.IntegerField(null=True)
crown_bnd = models.CharField(max_length=20,null=True)
pinion_bnd = models.CharField(max_length=20,null=True)
active = models.BooleanField(default=True)
chasis = models.CharField(max_length=20,null=True)
rear_axis = models.CharField(max_length=30,null=True)
front_axis = models.CharField(max_length=30,null=True)
front_tire_diam = models.IntegerField(null=True)
rear_tire_diam = models.IntegerField(null=True)
front_tire_width = models.IntegerField(null=True)
rear_tire_width = models.IntegerField(null=True)
collection_desc = models.CharField(max_length=30,null=True)
bench_desc = models.CharField(max_length=30,null=True)
Total_weight = models.IntegerField(null=True)
def __str__(self):
return self.modelid, self.model_desc
With a form based on that model:
class FormAltaSlotModel(ModelForm):
class Meta:
model = Slotmodels
fields = ['modelid','model_desc','categoryid','shopid','brandid','reference','history','year','purchase_price',
'actual_price','limited_edition','color','number','livery','sponsor','scale','engine','eng_position',
'crown','pinion','crown_bnd','pinion_bnd','active','chasis','rear_axis','front_axis','front_tire_diam',
'rear_tire_diam','front_tire_width','rear_tire_width','collection_desc','bench_desc','Total_weight']
help_texts = {
}
widgets = {
'history': Textarea(attrs={'cols': 30, 'rows': 2}),
'model_desc': Textarea(attrs={'cols': 30, 'rows': 2})
}
When I instance the form to create a record, is everything ok!. It is important to say that I have three foreignkey fields so when I render the form , the list values of the model referenced appear in the screen. And, the values are recorded properly (in the related Id fields).
The point is when I tried to update a record previously recorded. In the screen appear the descriptions and the list is not appearing, then the values that are passed to the form are descriptions instead of the codes, so the message "Select a valid choice. That choice is not one of the available choices.", appear for the three foreignkey fields that are 'categoryid','shopid','brandid'.
I have tried to fix it, but with no success. Thanks in advance!
Here I tried to do full CRUD with your MODEL & MODELFORM
view.py
def InsertData(request):
my_data = Slotmodels.objects.all() # Show data of Student Table
if request.method == 'POST':
form = FormAltaSlotModel(request.POST,request.FILES)
if form.is_valid():
form.save()
messages.success(request,'Student Successfully Inserted')
return redirect('/')
else:
form = FormAltaSlotModel()
context= {'form':form,'my_data':my_data}
return render(request,'home.html',context)
def UpdateData(request,modelid):
my_data = Slotmodels.objects.all() # Show data of Student Table
set_student = Slotmodels.objects.get(modelid=modelid)
if request.method == 'POST':
form = FormAltaSlotModel(request.POST,request.FILES,instance=set_student)
if form.is_valid():
form.save()
messages.success(request,'Student Successfully Updated')
return redirect('/')
else:
form = FormAltaSlotModel(instance=set_student)
context= {'form':form,'my_data':my_data}
return render(request,'home.html',context)
def DeleteData(request,modelid):
set_student = Slotmodels.objects.get(modelid=modelid)
set_student.delete()
messages.success(request,'Student Successfully Deleted')
return redirect('/')
urls.py
urlpatterns = [
path('', InsertData,name='insert_data'),
path('up/<int:modelid>/', UpdateData,name='update_data'),
path('del//<int:modelid>/', DeleteData,name='delete_data'),
]
HTML Code
<div class="container my-5">
<div class="row">
<div class="col-12">
<form action="" method="POST">
{% csrf_token %}
{{form.as_p}}
<button type="submit">Add</button>
</form>
</div>
<div class="col-12">
<table class="table">
<thead>
<tr>
<th scope="col">No.</th>
<th scope="col">Categories</th>
<th scope="col">Shops</th>
<th scope="col">Brands</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
{% for i in my_data %}
<tr>
<td>{{forloop.counter}}</td>
<td>{{i.categoryid}}</td>
<td>{{i.shopid}}</td>
<td>{{i.brandid}}</td>
<td>
Update
Delete
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
Output
I'm stuck with the issue that I need to insert the list [ ] in the model field while using SQLite,
Group_Model.py:
class ClassificationGroup(models.Model):
vendor_id = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None, null=True)
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
classification_id = models. [what do i take here to make it capable to store list of ids that will be related to the classification table.]
Classification_Model.py
class Classification(models.Model):
id = models.IntegerField()
name = models.CharField(max_length=100)
description = models. CharField(max_length=1000)
domain_name = models.CharField(max_length=200)
i just want to store the list of classification in the one field of the Classification Group Mentioned above, Please help me out in this.
Add a method to your class to convert it automatically.
import json
class ClassificationGroup(models.Model):
#...
classification_id = models.CharField(max_length=200)
def set_classification_id (self, lst):
self.classification_id = json.dumps(lst)
def get_classification_id (self):
return json.loads(self.classification_id)
your view:
obj = ClassificationGroup.objects.create(name="name",**data)
obj.set_classification_id([1,2,3])
obj.save()
#there are several examples of using this method
your HTML:
{% for obj in objects %}
{{ obj.name }}
{{ obj.get_classification_id }}
{% endfor %}
I know beginners can ask stupid questions but that is the way trough all it.
Is it possible that i can list all this images in a carousel? or image gallery. How can i list this images easiest?
What would you suggest?
I don't want to use foreignkey because I cannot (I couldn't yet understand the save process in the views) save a separate model in a view.
Thanks a lot
class MyFamily(models.Model):
author = models.ForeignKey(Profile, on_delete=models.CASCADE)
date = models.DateField(auto_now_add=True)
update = models.DateField(auto_now=True)
title = models.CharField(max_length=100)
explanatipon = models.TextField(blank=True)
photo1 = models.ImageField(upload_to='posts/photos/')
photo2 = models.ImageField(upload_to='posts/photos/')
photo3 = models.ImageField(upload_to='posts/photos/')
photo4 = models.ImageField(upload_to='posts/photos/')
photo5 = models.ImageField(upload_to='posts/photos/')
active = models.BooleanField(default=True)
def __str__(self):
return str(self.title)[:30]
i tried to make it like #willem-van-onsem mentioned it but without success. I NEED HELP PLEASE
What did I do :
MODELS PROFILE:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField()
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.user.username)
MODELS MYFAMILY:
class MyFamily(models.Model):
author = models.ForeignKey(Profile, on_delete=models.CASCADE)
date = models.DateField(auto_now_add=True)
update = models.DateField(auto_now=True)
title = models.CharField(max_length=100)
explanatipon = models.TextField(blank=True)
photo1 = models.ImageField(upload_to='posts/photos/')
photo2 = models.ImageField(upload_to='posts/photos/')
photo3 = models.ImageField(upload_to='posts/photos/')
photo4 = models.ImageField(upload_to='posts/photos/')
photo5 = models.ImageField(upload_to='posts/photos/')
active = models.BooleanField(default=True)
#property
def photos(self):
photos = [self.photo1, self.photo2, self.photo3, self.photo4, self.photo5]
return [photo for photo in photos if photo is not None]
def __str__(self):
return str(self.title)[:30]
VİEWS :
def photo(request):
myfamily = MyFamily.objects.filter(active=True)
context = {
'myfamily':myfamily
}
return render(request, 'posts/create-form.html')
You can return the photo's in a list:
class MyFamily(models.Model):
# …
#property
def photos(self):
photos = [self.photo1, self.photo2, self.photo3, self.photo4, self.photo5]
return [photo for photo in photos if photo is not None]
If you construct a view where you pass the MyFamily object as myfamily to the template render engine, we can generate HTML for a Bootstrap carousel:
<div id="carouselExampleSlidesOnly" class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
{% for photo in myfamily.photos %}
<div class="carousel-item {% if forloop.first %}active{% endif %}">
<img class="d-block w-100" src="{{ photo.url }}" alt="First slide">
</div>
{% endfor %}
</div>
</div>
That being said, I think the modelling might be improved with an extra model. Right now one can only upload exactly five object. Normally one defines an extra model (MyFamilyPhoto) with a ForeignKey to the MyFamily in this case to allow to generate an arbitrary number of MyFamilyPhotos for each MyFamily. For an arbitrary MyFamily object, you will need to add a parameter to the url. In the view you can obtain the myfamily of the user with:
from django.contrib.auth.decorators import login_required
#login_required
def photo(request):
myfamily = MyFamily.objects.get(active=True, author__user=request.user)
context = {
'myfamily': myfamily
}
return render(request, 'posts/create-form.html')
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
Is there a way to stop a model in django allowing an empty model to be saved?
e.g. I have a simple contact form
class Contact(models.Model):
alphabetical = RegexValidator(r'^[a-zA-Z]*$', 'Only alphabetical characters
are allowed', 'Invalid input')
name = models.CharField(max_length=200, validators=[alphabetical])
email = models.EmailField(validators=[EmailValidator, ])
subject = models.CharField(max_length=200)
message = models.CharField(max_length=250)
created_date = models.DateTimeField(auto_now_add=True)
How can I prevent an empty model being saved? e.g. in the django shell I can do
contact = Contact()
contact.save()
This gives a model with all blank values saved.
for validation you have to use django.forms. django forms will manage the validation part:
for eg: if your model.py is:
class Contact(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
subject = models.CharField(max_length=200)
message = models.CharField(max_length=250)
created_date = models.DateTimeField(auto_now_add=True)
now create a view in views.py :
from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Contact
def manage_contacts(request):
ContactFormSet = modelformset_factory(Contact, fields=('name', 'email', 'subject', 'message'))
if request.method == 'POST':
formset = ContactFormSet(request.POST)
if formset.is_valid(): # check the validation for blank fields
formset.save()
# do something.
else:
formset = ContactFormSet()
return render(request, 'manage_contacts.html', {'formset': formset})
create a template in templates/manage_contacts.html:
<form method="post">
{{ formset }}
</form>