First of all I want to apologize for my English. It's hard for me to write this question in English, but I didn't find any ideas for my problem on russian sites. So, I want to create a timetable on school-site. In my models.py :
class Classes(models.Model):
class Meta:
db_table = 'classes'
verbose_name_plural = "School_classes"
verbose_name = "School_class"
name = models.CharField(max_length=50, unique=True, verbose_name = 'School_classes')
def __str__(self):
return self.name
class Lessons(models.Model):
class Meta():
db_table = "lessons"
verbose_name_plural = "Lessons"
verbose_name = "Lessons"
lessons_class = models.ForeignKey(Classes)
lessons_creationdate = models.DateField()
lessons_weekcontent = RichTextField()
Then, in forms.py I have:
class LessonsForm(forms.ModelForm):
classname = forms.ModelChoiceField(queryset = Classes.objects.all(),empty_label="Choose a class",widget=forms.Select(attrs={'class':'dropdown'}),label="School_classes")
class Meta:
model = Lessons
fields = ('lessons_class',)
And in my views.py:
def ShowTimetable(request):
LForm = LessonsForm(request.POST or None)
args = {}
args['classes'] = Classes.objects.all()
args['lessons'] = Lessons.objects.all()
args['showlessons'] = LForm
args.update(csrf(request))
if request.method == 'POST' and LForm.is_valid():
CurrentClass = LForm.cleaned_data('currentclass', None)
args['class_name'] = CurrentClass
args['lessons'] = Lessons.objects.filter(lessons_class = CurrentClass)
if args['lessons']:
return render_to_response('Weekcontentpage.html',args )
else:
return render_to_response('Weekcontentpage_null.html',args )
else:
return render_to_response('myview.html',args )
Finally, in myviews.html
{% extends 'base.html' %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ showlessons }}
<input type="submit" value="Show timetable">
</form>
{% endblock %}
In Weekcontentpage.html:
{% extends "base.html" %}
{% block content %}
<h4>On request "{{ class_name }}:</h4>
{% for lesson in lessons %}
<h6>Date:{{ lesson.lessons_creationdate }}</h6>
<h4>{{ lesson.lessons_weekcontent }}</h4>
{% endfor %}
{% endblock content %}
and in Weekcontentpage_null.html:
{% extends "base.html" %}
{% block content %}
<h4> On "{{class_name}}" is nothing found :( (</h4>
{% endblock content %}
Now, after I make a choice in the drop down menu and push 'Show timetable' button, I've just see "None" and nothing is found :(. I understand that the problem in views.py, so i cant get a value from drop down, but I don't know how can i fix it. So i would appreciate any help. Thanks and sorry for my English:)
The same way as with any other field.
The problem is that you have defined a form class, but you are not using it in any way at all. Instead of ignoring the form and getting data from request.POST, you should be instantiating the form with the POST data, calling is_valid() on it, then getting the result from form.cleaned_data.
Related
how can I retrieve the lesson modules by its parent lesson strictly? e.g if I change to the next lesson where at the same contains a lessonmodule /lesson1/task1 this one shouldn't display since it doesn't belong to lesson2? how can I fix this by only retrieve slugs, content by the lesson attach to?
views
class LessonDetailView(LoginRequiredMixin, View):
login_url = "/account/login/"
def get(self, request, course_slug, lesson_slug, *args, **kwargs):
lesson = get_object_or_404(Lesson.objects.select_related('course'), slug=lesson_slug, course__slug=course_slug)
lessonmodule = get_object_or_404(LessonModule.objects.select_related('lesson'), slug='hello_world')
context = {
'object': lessonmodule,
'previous_lesson': lesson.get_previous_by_created_at,
'next_lesson': lesson.get_next_by_created_at,
}
return render(request, "courses/lesson_detail.html", context)
models
class Lesson(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=25,unique=True)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('lesson-detail',
kwargs={
'course_slug': self.course.slug,
'lesson_slug': self.slug
})
class LessonModule(models.Model):
slug = models.SlugField(unique=True, blank=True, null=True)
content = models.TextField()
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE)
allowed_memberships = models.ManyToManyField(Membership)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, blank=True)
def __str__(self):
return self.slug
template
{% block content %}
<div class='container'>
<h1>Lesson Detail View</h1>
<div class='row'>
<div class='col-sm-6 col-md-6'>
{% if object is not None %}
<h3>{{ object.title }}</h3>
<p>{{ object.course.description }}</p>
{{object}}
{% if previous_lesson %}
Back
{% endif %}
{% if next_lesson %}
Next
{% endif %}
{% else %}
<h3>Upgrade membership</h3>
<p>To view this course you'll need to upgrade your membership</p>
<br>
<hr>
{% endif %}
</div>
</div>
</div>
{% endblock content %}
As I can see here, you can have multiple LessonModule for a single Lesson due to one-to-many relation between Lesson and LessonModule(ForeignKey relation basically). You can fetch all the LessonModules like this(using reverse query):
# view
def get(self, request, course_slug, lesson_slug, *args, **kwargs):
lesson = get_object_or_404(Lesson.objects.select_related('course').prefetch_related('lessonmodule_set'), slug=lesson_slug, course__slug=course_slug)
context = {
'object': lesson,
'previous_lesson': lesson.get_previous_by_created_at,
'next_lesson': lesson.get_next_by_created_at,
}
return render(request, "courses/lesson_detail.html", context)
# template
{% for lesson_module in object.lessonmodule_set.all %}
{{ lesson_module.slug }}
{% endfor %}
I am just sending the Lesson object to template, and using reverse query in template to get LessonModule objects.
I have 2 models:
class Director(models.Model):
director_name = models.TextField(primary_key=True)
director_firstname = models.CharField(max_length=32)
def __str__(self):
return f'{self.director_name}'
def get_absolute_url(self):
return reverse('director-detail', args=[str(self.director_name)])
class Meta:
managed = False
db_table = 'director'
ordering = ['director_name']
class Connection(models.Model):
director_connect = models.ForeignKey('Director', models.DO_NOTHING, db_column='director_connect')
worker_connect = models.ForeignKey('Worker', models.DO_NOTHING, db_column='worker_connect')
class Meta:
managed = False
db_table = 'connection'
unique_together = (('director_connect', 'worker_connect'),)
ordering = ['director_connect']
def __str__(self):
return f'{self.director_connect}'
def get_absolute_url(self):
return reverse('director-detail', args=[str(self.director_connect)])
This is my view.py file:
class DirectorDetailView(generic.DetailView):
model=Director
template_name = 'company/director_detail.html'
def get_context_data(self, **qwargs):
a = super(DirectorDetailView, self).get_context_data(**qwargs)
a['cons'] = Connection.objects.all()
return a
When I am trying to match 2 columns in html with for loop and if statement, they do not match, although they are similar one to one copies of each other:
{% extends "index.html" %}
{% block content %}
<h1>{{ director.director_name }}</h1>
<p>{{ director.firstname }}</p>
{% for con in cons %}
{% if object.director_name == con.director_connect %}
<li>{{con.id}}, {{con.director_connect}}, {{con.worker_connect}}</li>
{% endif %}
{% endfor %}
{% endblock %}
How could I fix it? I would like to bring the list of workers under director's name. Any link to probable answer (I was looking for it, but I couldn't find it) or slight push towards the right direction would be nice.
The issue is that in your template you're comparing the director's name with the primary key that's referenced in the Connection by means of the director_connect ForeignKey. The simplest solution would be to change the if expression:
{% extends "index.html" %}
{% block content %}
<h1>{{ director.director_name }}</h1>
<p>{{ director.firstname }}</p>
{% for con in cons %}
{% if object == con.director_connect %} // Change it so it compares the primary key
<li>{{con.id}}, {{con.director_connect}}, {{con.worker_connect}}</li>
{% endif %}
{% endfor %}
{% endblock %}
Other way to achieve this would be to filter the workers by director in the view, using filter:
class DirectorDetailView(generic.DetailView):
model=Director
template_name = 'company/director_detail.html'
def get_context_data(self, **qwargs):
a = super(DirectorDetailView, self).get_context_data(**qwargs)
director = self.get_object()
a['cons'] = Connection.objets.filter(direct_connect=director).all()
return a
This is better because it will filter the workers in the database using SQL which is probably faster than the template engine.
Other solution would be to use a ManyToManyField and let django ORM take care of the relations for you, but that would require refactoring the code and maybe some database migrations.
I get a ValueError at /new_animal/7/ here is the error message:invalid literal for int() with base 10: b'11 02:07:39.299546'
It sends me to my base.html file saying there's an error at "line 0".
My base.html file contains the bootstrap.
Here is my new_animal.html file:
{% extends "zoo_animal_feeders/base.html" %}
{% load bootstrap3 %}
{% block header %}
<h2>{{ animal_type }}</h2>
<h2>Add new animal:</h2>
{% endblock header %}
{% block content %}
<form action="{% url 'zoo_animal_feeders:new_animal' animal_type.id %}" method='post' class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name='submit'>add animal</button>
{% endbuttons %}
</form>
{% endblock content %}
Let me know if I need to show you more of my project.
Update
Here is my views code:
#login_required
def new_animal(request, animal_type_id):
"""Add a new animal to an animal type"""
animal_type = AnimalType.objects.get(id=animal_type_id)
if request.method != 'POST':
#create a blank form
form = AnimalForm()
else:
#POST data submitted
form = AnimalForm(data=request.POST)
if form.is_valid():
new_animal = form.save(commit=False)
new_animal.animal_type = animal_type
new_animal.save()
return HttpResponseRedirect(reverse('zoo_animal_feeders:animal_type', args=[animal_type_id]))
context = {'animal_type':animal_type, 'form':form}
return render(request, 'zoo_animal_feeders/new_animal.html', context)
Here is my models code:
class AnimalType(models.Model):
"""Type of animal that can classify the animal"""
owner = models.ForeignKey(User, on_delete=models.CASCADE)
a_type = models.CharField(max_length=50, default='')
date_added = models.DateField(auto_now_add=True)
def __str__(self):
return self.a_type
The solution was that in my models field I had date_added = models.DateField(auto_now_add=True) and I changed it to date_added = models.DateTimeField(auto_now_add=True) and it then worked.
It was because somewhere on the page I had it formatted as a DateTimeField and not a DateField.
Im trying to access the detailpage of a photo instance, but I can't seem to get it to work. (The category detail page works great!)
I would like to access http//domain.com/main-category/sub-cat/sub-sub-cat/photo-slug/
Models.py:
from mptt.models import MPTTModel, TreeForeignKey
class Category(MPTTModel):
name = models.CharField('category name', max_length=32)
parent = TreeForeignKey('self', null=True, blank=True, verbose_name='parent category', related_name='categories')
slug = models.SlugField(unique=True)
def get_absolute_url(self):
return reverse('gallery', kwargs={'path': self.get_path()})
class Photo(models.Model):
name = models.CharField('photo name', max_length=32)
parent = TreeForeignKey(Category, verbose_name='parent category', related_name='photos')
slug = models.SlugField()
class Meta:
unique_together = ('slug', 'parent')
urls.py:
url(r'^(?P<path>.*)', mptt_urls.view(model='gallery.models.Category', view='gallery.views.category', slug_field='slug'), name='gallery'),
views.py:
def category(request, path, instance):
return render(
request,
'gallery/category.html',
{
'instance': instance,
'children': instance.get_children() if instance else Category.objects.root_nodes(),
}
)
How is it possible to access the photo model using mtpp-urls ?
Edit 1:
Sorry, when I try a url like http//domain.com/main-category/sub-cat/sub-sub-cat/photo-slug The template display the Gallery main page because there is no instance when I try the url with the photo-slug (and yes, the photo has the category as a parent :)
Here is the category.html template:
<html>
<head>
<title>{% if instance %}{{ instance.name }}{% else %}Gallery main page{% endif %}</title>
</head>
<body>
<h3>{% if instance %}{{ instance.name }}{% else %}Gallery main page{% endif %}</h3>
Gallery main page
{% for ancestor in instance.get_ancestors %}
> {{ ancestor.name }}
{% endfor %}
> <strong>{{ instance.name }}</strong>
<h4>Subcategories:</h4>
<ul>
{% for child in children %}
<li>{{ child.name }}</li>
{% empty %}
<li>No items</li>
{% endfor %}
</ul>
<h4>Photos:</h4>
<ul>
{% for object in instance.photos.all %}
<li>{{ object.name }}</li>
{% empty %}
<li>No items</li>
{% endfor %}
</ul>
</body>
</html>
The reason why it doesn't work is that MPTT only works on one model at a time, in that case the gallery, not the photo.
So actually, in your models the Gallery is NOT the parent of the photo, but just a foreign key on the photo.
If you know that the last element of the slug is always a photo, you could probably create an intermediate view like this:
urls.py:
url(r'^(?P<path>.*)', views.photo, name='photo'),
views.py:
def photo(self, path=''):
path_parts = path.split('/')
gallery_path = '/'.join(path_parts[:-1])
photo_slug = path_parts[-1]
return mptt_urls.view(model='gallery.models.Category', view='gallery.views.photo_in_category', slug_field='slug')({'path': gallery_path, 'photo_slug': photo_slug})
def photo_in_category(request, path, gallery_instance, photo_slug=None):
photo_instance = Photo.objects.get(parent=gallery_instance, slug=photo_slug)
...
Otherwise, you may need to differentiate the URLS (which would also bring simpler code):
urls.py:
url(r'^photo/(?P<path>.*)/(?P<photo_slug>[-\w]+)/$', mptt_urls.view(model='gallery.models.Category', view='gallery.views.photo_in_category', slug_field='slug'), name='photo'),
url(r'^gallery/(?P<path>.*)/$', mptt_urls.view(model='gallery.models.Category', view='gallery.views.category', slug_field='slug'), name='gallery'),
I have some problem
This is my code:
views.py:
def cv_detail(request, pk):
cv = get_object_or_404(Cv, pk=pk)
return render(request, 'cv_detail.html', {'cv': cv})
cv_detail.html:
{% block profile %}
<a class="btn-lg btn-default" href="{% url "edit_cv" pk=cv.pk %}"><span class="glyphicon glyphicon-pencil"> Edit</span></a>
<p></p><br>
<div class="jumbotron">
{% if not cv.specialization.is_empty %}
<p>Specialization: {{cv.specialization}}</p>
{% endif %}
</div>
{% endblock %}
forms.py:
class CvForm(forms.ModelForm):
class Meta:
model = Cv
fields = ('name', 'specialization',)
models.py:
class Cv(models.Model):
author = models.ForeignKey('auth.User')
name = models.CharField(max_length=25, null = True)
specialization = models.CharField(max_length=30, blank=True, null=True)
def zapisz(self):
self.save()
def __str__(self):
return self.surname
And the question is: how can i check is any field of cv model is empty?
I have nothing in "Specialization" - is not complemented by me, so shouldn't be displayed, but it is, like: "Specialization: ".
Any ideas how to check? Becouse that what i have is not working :/
Thanks!
You can check for an empty specialization field in your template with:
{% if cv.specialization and cv.specialization.strip %}
<p>Specialization: {{cv.specialization}}</p>
{% endif %}
The .strip check will ensure that you do not attempt to display a string that only contains whitespaces.