The general task: there is a list of the events which are displayed in a table view, the user clicks on the event and gets redirected to a single event page, which displays extra information about an event.
There is a button on this template that should give functionality to record some data of the event in the user-selected events list.
And I really don't get how to pass the event data into the form to create the user_event, maybe I chose the wrong way to create the instance of the model?
Models.py
class Event(models.Model):
LANGUAGE_CHOICES = [
('EN', 'English'), ('IT', 'Italian'), ('FR', 'French'), ('DE', 'German'), ('RU', 'Russian'), ]
STATUS_CHOICES = [('draft', 'Draft'), ('confirmed', 'Confirmed'), ]
FORMAT_CHOICES = [('live', 'Live'), ('online', 'Online'), ]
TOPIC_CHOICES = [('cataract', 'Cataract'),
('vitreo', 'Vitreoretinal'),
('optometry', 'Optometry'),
('multi', 'Multidisciplinary'),
('plastic', 'Plastic and Reconstructive surgery'),
('onco', 'Ocular oncology'),
('glaucoma', 'Glaucoma'),
('pediatrics', 'Pediatrics'), ]
title = models.CharField(
max_length=250, verbose_name='Event', db_index=True, default="Event")
slug = models.SlugField(max_length=250, unique_for_date='publish')
kol = models.ManyToManyField(
Kol, verbose_name='Presenter', db_index=True, blank=True)
body = models.TextField(verbose_name='Description', blank=True)
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
sponsor = models.CharField(
max_length=150, verbose_name='Sponsored by', default='')
organizer = models.CharField(
max_length=150, verbose_name='Organized by', default='')
topic = models.CharField(
max_length=100, choices=TOPIC_CHOICES, default='multi', verbose_name='Discipline')
status = models.CharField(
max_length=100, choices=STATUS_CHOICES, default='draft')
event_format = models.CharField(
max_length=50, choices=FORMAT_CHOICES, default='online', verbose_name='Format', db_index=True)
main_language = models.CharField(
max_length=50, choices=LANGUAGE_CHOICES, default='EN', verbose_name='Main language', db_index=True)
event_url = models.URLField(blank=True)
event_date_start = models.DateField(
verbose_name='Start date', db_index=True)
event_time_start = models.TimeField(default='09:00')
event_date_finish = models.DateField(
verbose_name='End date', auto_now=True)
event_time_finish = models.TimeField(default='18:00')
is_cme = models.BooleanField(
default=False, verbose_name='CME credits', db_index=True)
objects = models.Manager() # the default manager
published = PublishedManager() # published manager
futured = FutureManager() # future dates only
# follow check
users_follow = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name='events_liked', blank=True)
class Meta:
ordering = ('event_date_start',)
def __str__(self):
return self.title
def get_kols(self):
return "\n".join([str(p) for p in self.kol.all()])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Event, self).save(*args, **kwargs)
#property
def _month(self):
return datetime.date(self.event_date_start).month
event_month = property(_month)
def get_absolute_url(self):
return reverse('events:event_detail', args=[self.publish.year,
self.publish.strftime(
'%m'),
self.publish.strftime(
'%d'),
self.slug])
class UserEvent(models.Model):
follower = models.ForeignKey(
User, related_name='user_events', on_delete=models.CASCADE)
my_event = models.ForeignKey(
Event, related_name='selected_event', on_delete=models.CASCADE)
title = models.CharField(
max_length=250, verbose_name='Event', db_index=True, default="Event")
event_url = models.URLField(blank=True)
event_date_start = models.DateField(
verbose_name='Start date')
event_date_finish = models.DateField(
verbose_name='End date')
class Meta:
ordering = ['-event_date_start']
def save(self, *args, **kwargs):
created = not self.pk
super().save(*args, **kwargs)
if created:
UserEvent.objects.create(user=self)
def __str__(self):
return self.title
forms.py
class UserEventForm(forms.ModelForm):
class Meta:
model = UserEvent
fields = ("title", "event_url",
"event_date_start", "event_date_finish")
detail.html with the button
{% extends 'bbase11.html' %} {% block title %} {{ event.title}} {% endblock %} {% block content %}
<div class="container">
<h1> {{ event.title }}</h1>
<p class='event_descr'> {{event.body}}</p>
<p> Presenting professionals {{event.get_kols}}</p>
<div>Organized by {{event.organizer}}</div>
<div>Sponsored by {{event.sponsor}}</div>
<div>
<form action= "{% url "events:add_event" %}" method = "POST" >
{{form.as_p}}
{% csrf_token %}
<input id='event' type='hidden' value = {{event.id}}>
<button type="submit" class="btn btn-outline-primary btn-sm m-0 waves-effect">Add to calendar</button></div>
</form>
</div>
{% endblock %}
views.py
def event_detail(request, year, month, day, event):
event = get_object_or_404(Event, slug=event,
status='confirmed',
publish__year=year,
publish__month=month,
publish__day=day)
return render(request, 'events/event/detail.html', {'event': event, 'add_event': add_event})
#login_required
def add_event(request):
if request.method == 'POST':
form = UserEventForm(request.POST or None)
if form.is_valid():
form.save()
messages.success(request, ("Event has been added"))
return redirect('event_list')
else:
messages.error(request, ("Event has not been added"))
return redirect('events:event_list')
else:
events = Event.futured.all()
return render(request, 'list.html', {'events': events})
Using a class based view instead of your function based one, you can override the get_initial method as follows:
class AddEventCreateView(CreateView):
model = Event
form_class = UserEventForm
template_name = 'your/template.html'
def get_initial(self):
initial = super().get_initial()
# Add your initial values here - for example
initial['title'] = 'Some value'
return initial
def form_valid(self, form):
self.object = form.save(commit=False)
# Do something here
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy('your:url-name')
You can now pass as many initial values to your form as needed. See http://ccbv.co.uk/projects/Django/3.0/django.views.generic.edit/CreateView/#get_initial for details.
It looks like it may be a typo in the URL in the detail.html with the quotes.
Change this:
<form action= "{% url "events:add_event" %}" method = "POST" >
To this:
<form action="{% url 'events:add_event' %}" method="POST">
Related
When I query all the comments of the post, I want to return the user's username.
My two Models:
class Comment(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
post = models.ForeignKey(
Post, on_delete=models.CASCADE, null=False, blank=False)
title = models.TextField()
date = models.DateField(auto_now=True)
class User(AbstractUser):
objects = UserManager()
username = models.CharField(max_length=60, unique=True)
avi_pic = models.ImageField(
_('avi_pic'), upload_to=aviFile, null=True, blank=True)
My Comments Serializer:
class CommentSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField('get_username_from_user')
avi_pic = serializers.SerializerMethodField('get_avi_pic')
class Meta:
model = Comment
fields = '__all__'
def get_username_from_user(self, comment):
username = comment.user.username
return username
def get_avi_pic(self, comment):
request = self.context['request']
avi_pic = comment.user.avi_pic.url
return request.build_absolute_uri(avi_pic)
My Comments View:
class CommentView(APIView):
authentication_class = [authentication.TokenAuthentication]
permission_class = [permissions.IsAuthenticated]
serializer_class = CommentSerializer
# Get all comments from current post
def get(self, request):
post_id = request.data.get('id')
post = Post.objects.get(id=post_id)
comment = Comment.objects.filter(post=post).values()
serializer = CommentSerializer(comment)
return Response(serializer.data, status=status.HTTP_200_OK)
In my console I get: 'QuerySet' object has no attribute 'user'
Appreciate any help!!
In views.py:
comment = Comment.objects.filter(post=post)
In serializer.py:
def get_username_from_user(self, comment):
username = comment.user.username
return username
In views.py:
def get(self, request):
...
serializer = CommentSerializer(comment, many=True)
...
In my humble opinion, your problem is not having a ForeignKey for the "User" model, meaning whatever model you are trying to render doesn't have a column named 'user'. I'd do something like this:
models.py
class User(AbstractUser):
pass
def __str__(self):
return f"{self.username}"
class Comment(models.Model):
comment = models.TextField(max_length=300, null=True)
creation_date = models.DateTimeField(default=timezone.now)
user = models.ForeignKey(User, on_delete=models.CASCADE)
whatever_name = models.ForeignKey(whatever_model_to_relate, on_delete=models.CASCADE, related_name="comments")
forms.py
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ['comment']
widgets = {
'comment': forms.Textarea(attrs={'rows':4, 'cols':100}),
}
views.py
#login_required
def whatever_function(request, id):
whatever_name = whatever_related_model.objects.get(id=id)
return render(request, "template.html", {
"whatever_name_for_template": whatever_name,
"commentform": CommentForm()
})
template.html
{% for comment in whatever_related_model.comments.all %}
<div class="card p-1 m-2 col-lg-12 col-sm-12">
<div class="card-body">
<h5 class="card-title">{{ comment.user }}</h5>
<h6 class="card-subtitle mb-2 text-muted">{{ comment.creation_date }}</h6>
{{ comment.comment }}
</div>
</div>
{% endfor %}
Hopefully I didn't get sidetracked from your question.
I am trying to create a JobRequestFile form where you can upload multiple files involving a foreign key to my JobRequest model. However, when trying to save, it takes me to my JobRequest form and says these fields are required.
my form:
class Meta:
model = JobRequestFile
fields = [
'file'
]
widgets = {
'file': ClearableFileInput(attrs={'multiple': True}),
}
my view:
class FileUpload(FormView):
form_class = JobRequestFileForm
template_name = 'jobrequest/upload.html' # Replace with your template.
success_url = 'loggedIn'
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
files = request.FILES.getlist('file')
if form.is_valid():
most_recent_jr = JobRequest.get.latest('requestDate')
for f in files:
JobRequestFile.object.create(jobRequest=most_recent_jr, file=f)
return self.form_valid(form)
else:
return self.form_invalid(form)
My template:
<form action='.' method='POST' enctype='multipart/form-data'>
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Save' />
</form>
The two models:
class JobRequest(models.Model):
customer = models.ForeignKey('account.Customer', on_delete=models.CASCADE)
partnerTypeNeeded = models.CharField('PartnerTypeNeeded', max_length=30, choices=PartnerMore.PartnerTypes.choices)
issueDescription = models.TextField(blank=True)
communa = models.CharField(unique=False, max_length=30, default='0')
serviceDate = models.DateTimeField()
requestDate = models.DateTimeField(auto_now_add=True, null=False, blank=False)
budget = models.FileField(upload_to='budget/%Y/%m/', null=True, blank=True)
jobCompleted = models.BooleanField(default=False)
partner = models.ForeignKey('account.Partner', on_delete=models.SET_NULL, null=True, blank=True, related_name='assignedPartner')
suggestedPartner = models.ForeignKey('account.Partner', on_delete=models.SET_NULL, null=True, blank=True, related_name='suggestion')
class JobRequestFile(models.Model):
jobRequest = models.ForeignKey('JobRequest', on_delete=models.CASCADE)
file = models.FileField(upload_to='files/%Y/%m/')
I have created a form for a Post. The form loads and when I enter all the value and try to submit the form, it gets refreshed but the database is not updated.
Here is my Post Model:
class Post(models.Model):
no_people = models.IntegerField()
no_days = models.IntegerField()
tour_date = models.CharField(max_length=200, blank=True)
Gender_types = (
('M', 'Male'),
('F', 'Female'),
('O', 'Others'),
)
Gender_prefer = models.CharField(max_length=1, choices=Gender_types)
location = models.CharField(max_length=200, blank=True)
pic_location = models.ImageField(blank=True, upload_to="posts/")
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
detail = models.TextField()
liked = models.ManyToManyField(Yatru, blank=True, related_name= 'likes')
author = models.ForeignKey(Yatru, on_delete=models.CASCADE, related_name = 'posts',null=True)
def __str__(self):
return str(self.location)
def no_likes(self):
return self.liked.all().count()
class Meta:
ordering = ('-created',)
def save(self, *args, **kwargs):
self.location = self.location.upper()
return super(Post, self).save(*args, **kwargs)
LIKE_CHOICES = (
('Like', 'Like'),
('Unlike', 'Unlike'),
)
Here is the form.py:
from django import forms
from .models import Post
class PostModelForm(forms.ModelForm):
class Meta:
model = Post
fields = ('no_people','no_days','tour_date', 'Gender_prefer','location','detail')
Here is the views.py:
def post_add(request):
user = request.user
profile = Yatru.objects.get(user=user)
form = PostModelForm(request.POST or None, request.FILES or None, instance=profile)
if request.method == 'POST':
if form.is_valid():
newpost=form.save(commit=False)
newpost.user=request.user
newpost.save()
return render(request, 'posts/my_post.html',{'form': form})
This is the HTML file:
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button type='submit'>Submit </button>
</form>
Hi please follow instructions:
First insert "author" field in field tuple of model form
In your post_add view change below line
newpost.author=request.user
Models
attendance_choices = (
('absent', 'Absent'),
('present', 'Present')
)
class Head_of_department(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.CharField(max_length=30)
def __str__(self):
return self.first_name
class Employee(models.Model):
first_name = models.CharField(max_length=200, unique=True)
last_name = models.CharField(max_length=200, unique=True)
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=100)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Attendance(models.Model):
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)
Views
class Attendancecreate(CreateView):
model = Attendance
fields = ['employee']
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
context['formset'] = AttendanceFormset(queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=email), initial=[{'employee': employee} for employee inself.get_initial()['employee']])
context['attendance_form'] = Attendanceform()
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
context["employees"] = Employee.objects.filter(head_of_department =hod)
return context
def get_initial(self):
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
initial = super(Attendancecreate , self).get_initial()
initial['employee'] = Employee.objects.filter(head_of_department=hod)
return initial
def post(self, request, *args, **kwargs):
formset = AttendanceFormset(queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=email), initial=[{'employee': employee} for employee inself.get_initial()['employee']))
if formset.is_valid():
return self.form_valid(formset)
def form_valid(self, formset):
instances = formset.save(commit=False)
for instance in instances:
instance.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
instance.save()
return HttpResponseRedirect('/dashboard/')
def form_invalid(self, formset):
print ('errors')
print (formset.errors)
Forms
class Attendanceform(ModelForm):
class Meta:
model = Attendance
fields = ('employee','attendance','hod')
AttendanceFormset = inlineformset_factory(Head_of_department,Attendance,fields=('attendance',))
Template
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
<br><br>
{% endfor %}
Error
Below shown square brackets was printed in the console when I used print(formset.errors)
[]
How to pass employees as initial values for attendance model as shown below in the images, employees will be rendered and rendered values have to be passed as employee in attendance model.
Is there any workaround with modelformset or inlineformset ? I can't get it right with the views I have included in the question .
I was missing request.post ,
class Attendancecreate(CreateView):
...
def post(self, request, *args, **kwargs,):
formset = AttendanceFormset(request.POST,queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=self.request.user.email), initial=[{'employee': employee} for employee in self.get_initial()['employee']])
if formset.is_valid():
return self.form_valid(formset)
Template
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.employee.initial }} {{ form.employee}} {{ form.attendance }}
<br><br>
{% endfor %}
Models
class Head_of_department(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.CharField(max_length=30)
def __str__(self):
return self.first_name
class Employee(models.Model):
first_name = models.CharField(max_length=200, unique=True)
last_name = models.CharField(max_length=200, unique=True)
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=100)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Attendance(models.Model):
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)
Views
class Attendancecreate(CreateView):
model = Attendance
fields = ['employee']
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
context["objects"] = self.model.objects.filter(employee__head_of_department =hod)
print (context["objects"])
return context
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
self.object.save()
return super().form_valid(form)
Template
<div class="form-group">
{% for item in objects %}
{{ item.employee }}
{% endfor %}
</div>
The webapp has a login feature. The headofdepartment can mark the attendance . I want to render a list of employees under the respective logged in HOD and mark attendance . I want to do this in the same view .
I am unable to render the employees for logged in HOD.
I found the solution , I wrote views incorrectly.
model = Attendance
fields = ['employee']
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
context["objects"] = Employee.objects.filter(head_of_department =hod)
print (context["objects"])
return context
Template
{% for emp in objects %}
{{ emp.first_name }} {{ emp.last_name }}
{% endfor %}