how can i pass a context variable in a class. i know that i would use the render if i was showing my template from a function. and then i could just pass my context variable as part of the render. But how do i pass a context variable to html if i am using a class to show the template.
i have tried putting a function into my class but it has not worked.
views.py
class hithere(ListView):
model = Datadata
template_name = 'index.html'
def whatsup(request):
context = {}
context['my_string'] = "this is my sring"
return render(request, context)
Index.html
<h1> {{ my_string }} </h1>
You can override the .get_context_data(…) method [Django-doc]:
class hithere(ListView):
model = Datadata
template_name = 'index.html'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['my_string'] = 'this is my string'
return context
But perhaps more convenient is to define a method:
class hithere(ListView):
model = Datadata
template_name = 'index.html'
def my_string(self):
return 'this is my string'
and render this with:
{{ view.my_string }}
Note: normally a Django models, just like all classes in Python are given a name in PerlCase, not snake_case, so it should be: HitHereView instead of hithere.
Related
I want to get data with request.data.columns in frontend.I can do it with ViewSet with list method but how to do it with generics.APIView.
Below is my viewsets and generics code:
class TestList(viewsets.ViewSet):
queryset = Test.objects.all()
def list(self,request):
serializer = TestSerializer(self.queryset, many = True)
return Response({'columns': serializer.data})
class TestList(generics.RetriveAPIView):
queryset = Test.objects.all()
serializer_class = TestSerializer
class TestList(APIView):
queryset = Test.objects.all()
def list(self,request):
serializer = TestSerializer(self.queryset, many = True)
return Response({'columns': serializer.data})
change your urls.py like this.
path(r"url", TestList.as_view({"get": "list"}))
Correct code:
class TestList(APIView):
queryset = Test.objects.all()
def list(self,request):
queryset = self.get_queryset()
serializer = TestSerializer(queryset, many = True)
return Response({'columns': serializer.data})
Details about why i had to add queryset = self.get_queryset() instead of directly access self.queryset.From official drf documentation:
queryset - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the get_queryset() method. If you are overriding a view method, it is important that you call get_queryset() instead of accessing this property directly, as queryset will get evaluated once, and those results will be cached for all subsequent requests.
I'm starting to use class based views for an application I'm creating but I'm nots sure how it works.
What I need is to have three different templates, and each template will show different information depending on a model field. My question is if there's a way to have only one class view that can render three different html templates with 3 different contexts, or if I need to create 3 different classes.
Using function based views, I would just do this:
# def humanResourcesView(request):
# context = {
# 'data' : Document.objects.all().filter(documentType='humanResources'),
# }
# return render(request, 'main/hr.html', context)
# #view to display training documents after click
# def trainingView(request):
# context = {
# 'data' : Document.objects.all().filter(documentType='training'),
# }
# return render(request, 'main/training.html', context)
# #view to display resource documents after click
# def reportsView(request):
# context = {
# 'data' : Document.objects.all().filter(documentType='reports')
# }
# return render(request, 'main/reports.html', context)
But I'm not sure how it works with class based views. Currently I have this, which renders and filters data correctly for one template, but I don't know how to do multiple templates. Do I need to create 3 different classes?
class DocumentView(View):
def get(self, request, *args, **kwargs):
reports = Document.objects.all().filter(documentType="reports")
context = {
'reports' : Document.objects.all().filter(documentType='reports')
}
return render(request, 'documents/reportsDocs.html', context)
Is there a way to only have one class, and pass a certain context depen
You would need to inherit from TemplateView
and override the get_template_names method to return your conditional based template.
And you would override get_context_date to fetch the data accordingly.
from django.views.generic import TemplateView
class DocumentView(TemplateView):
def get_template_names(self):
pass
def get_context_data(self, **kwargs):
pass
views.py
def contact_us(request):
if request.method == 'POST':
formq = forms.querys(request.POST)
if formq.is_valid():
obj = query()
obj.name = formq.cleaned_data['your_name']
obj.email = formq.cleaned_data['your_email']
obj.message = formq.cleaned_data['your_message']
obj.save()
return redirect(index)
else :
formq = forms.querys()
return render(request, 'home/contact_us.html', {'formq': formq})
models.py
class query(models.Model):
Name = models.CharField(max_length=200)
Email = models.CharField(max_length = 200)
Message = models.CharField(max_length=1500)
def __str__(self):
return self.Name
forms.py
class querys(forms.ModelForm):
class Meta:
model=models.query
fields = ['Name', 'Email','Message']
Please Help with how can I add the query in the database and view it on the admin page.
There are multiple things that you need to see:
Since you are using ModelForm so you don't have to manually clean and save the data like you are doing.Calling save() method will do the job.
Moreover don't import entire forms and models. Import what is
necessary. Don't import the entire file.
You can't redirect to url name without using reverse. Please look at this reverse
This view is valid if you are using formq object in template i.e {{ formq }}. If you are making custom html form then make sure the name of <input> are same as django form fields.Assuming views.py and forms.py are in the same location.
views.py
from .forms import querys
from django.urls import reverse
from django.shortcuts import render,redirect
def contact_us(request):
if request.method == 'POST':
formq = querys(request.POST)
if formq.is_valid():
formq.save()
return redirect(reverse(index))
else:
return render(request, 'home/contact_us.html', {'formq': formq})
else:
formq = querys()
return render(request, 'home/contact_us.html', {'formq': formq})
Again assuming models.py and forms.py are in the same location.
forms.py
from .models import query
class querys(forms.ModelForm):
class Meta:
model=query
fields = ['Name', 'Email','Message']
Wondering what I'm doing wrong here. I'm running DRF with a React frontend. Trying to get one serializer to GET and POST a user's selected stations.
The AJAX POST works great, but the get on a page's initial load no longer works, and Django tells me: TypeError: 'Station' object is not iterable.
From reading around I'm vaguely aware that I shouldn't be declaring station with many = True, as this is causing the exception to be thrown. But I can't find any other way to get it working, it mangles the JSON POST request if I remove this option and stops the data validating.
The create is using custom code and is working fine.
Should I be trying to get this to work seamlessly or should I just hack it/make a different serializer to do the POST? Am I doing this in a logical way or have I got it all back-to-front?
models.py
class Station(models.Model):
network = models.ForeignKey(Network, on_delete=models.CASCADE)
name = models.CharField(db_column='name', max_length=256) # Field name made lowercase.
latitude = models.FloatField()
longitude = models.FloatField()
users = models.ManyToManyField('Account', through='UserStations')
class Meta:
managed = True
def __str__(self):
return self.name
class UserStations(models.Model):
station = models.ForeignKey(Station, on_delete=models.CASCADE)
user = models.ForeignKey(Account, on_delete=models.CASCADE)
serializers.py
class UserStationListSerializer(serializers.ModelSerializer):
class Meta:
model = Station
# fields = ('id', 'name')
fields = '__all__'
class UserStationsSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
#many = kwargs.pop('many', True)
print args
super(UserStationsSerializer, self).__init__(*args, **kwargs)
station = UserStationListSerializer(many=True, required = False, read_only=False)
views.py
class UserStationList(generics.ListCreateAPIView):
queryset = UserStations.objects.all()
serializer_class = UserStationsSerializer
Urls.py
from django.conf.urls import url
from . import views
from .views import StationList, AccountViewSet
from rest_framework.routers import DefaultRouter
from rest_framework.authtoken.views import obtain_auth_token
router = DefaultRouter()
router.register(r'users', AccountViewSet)
urlpatterns = router.urls
urlpatterns += [
url(r'^$', views.StationList.as_view(), name='station-list'),
url(r'user-station-list/', views.UserStationList.as_view(), name='user-station-list'),
url(r'^obtain-auth-token/$', obtain_auth_token),
url(r'station-list/', views.StationList.as_view(), name='user-station-list'),
]
My form.html
{{ form_field(task_form['execution_time']) }}
<input type="text" name="admin_time">
views.py
class CreateTaskView(LoginRequiredMixin, MyStaffUserRequiredMixin, generic.CreateView):
model = Task
form_class = TaskForm
template_name = 'tasks/form.html'
def get_context_data(self, *args, **kwargs):
ctx = super(CreateTaskView, self).get_context_data(*args, **kwargs)
ctx['task_form'] = ctx.get('form')
ctx['action'] = 'Add'
ctx['cancel_url'] = reverse('tasks.list')
return ctx
def form_valid(self, form):
form.save(self.request.user)
messages.success(self.request, _('Your task has been created.'))
return redirect('tasks.list')_url'] = reverse('tasks.list')
return ctx
When processing the form if admin_time has a value, then execution_time should be equal to admin_time.
How can I bring that about?
I want something like this- but it throws eror
def get_context_data(self, *args, **kwargs):
ctx = super(CreateTaskView, self).get_context_data(*args, **kwargs)
ctx['task_form'] = ctx.get('form')
if self.admin_time.is_valid():
task.execution_time=self.admin_time
else:
ctx['action'] = 'Add'
ctx['cancel_url'] = reverse('tasks.list')
return ctx
CreateView.get_context_data used to send additional context to your template (or override exist one) and it yields only when you have to render empty values request.GET
You can receive data on request.POST, so it yields methods in order (main of them) dispatch -> post -> form_valid or form_invalid -> redirect to success url. You can see there is no get_context_data so remove that weird code from get_context_data:
if self.admin_time.is_valid():
task.execution_time=self.admin_time
else:
I can see you override form_valid so if it runs - form already is valid and you can get "cleaned data" from it if you want perform some additional validation, put following code before form.save():
admin_time = form.cleaned_data['admin_time']
# check if it is not empty
if admin_time:
self.execution_time = admin_time
And you should not do this return ctx in your form_valid, because it never reach here after first return.
I also recommend you look at CreateView class implementation https://docs.djangoproject.com/en/1.7/ref/class-based-views/generic-editing/#createview and Django tutorials and docs if you want understand what you are doing https://docs.djangoproject.com/en/1.7/intro/tutorial01/ there ~ 6 tutorials, read and try it all and http://www.checkio.org/ for learning python. Because here we mainly don't loyal for such questions.