Doing a modified version of the polls tutorial. Comments work with the database when I go in the python manage.py shell but I can't get it to actually read the post data. Any time I post a comment, the page re-renders but no comment in the database.
Here are my models for an individual Entry and a Comment
import datetime
from django.db import models
from django.utils import timezone
from django.forms import ModelForm
class Entry(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
pub_date = models.DateTimeField('date published')
class Comment(models.Model):
entry = models.ForeignKey(Entry)
comment = models.TextField()
comment_date = models.DateTimeField()
In the Python shell, I'm able to create comments (that show up in the admin) perfectly.
>>> from blog.models import Entry, Comment
>>> e = Entry.objects.get(pk=1)
>>> from django.utils import timezone
>>> e.comment_set.create(comment="isn't it pretty to think so?", comment_date=timezone.now())
<Comment: isn't it pretty to think so?>
In the detail.html view of each blog entry, a user can add a comment.
<h1>{{ entry.title }}</h1>
<p>{{ entry.body }}</p>
<p>{{ entry.tags_set.all }}</p>
<form action="{% url 'blog:comment' entry.id %}" method="post">
{% csrf_token %}
<textarea name="comment101" style="width:300px; height: 70px; maxlength="300"; display:none;">
</textarea></br>
<input type="submit" name="comment101" value="Add comment" />
</form>
Views for detail and comment:
from django.utils import timezone
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from blog.models import Entry, Tags, Comment
def detail(request, entry_id):
entry = get_object_or_404(Entry, pk=entry_id)
return render(request, 'entries/detail.html', {'entry': entry})
def comment(request, entry_id):
p = get_object_or_404(Entry, pk=entry_id)
add_comment = request.POST['comment101']
#get input name comment from POST data
p.comment_set.create(comment="add_comment", comment_date=timezone.now())
return HttpResponseRedirect(reverse('blog:detail', args=(p.id)))
I've exhausted all I know. I tried adding name='comment101' every input/form in detail.html and my comment view replicates exactly what I did in the Python shell.
Lastly, if anyone could point me to something to debug code involving POST data (for Mac), that'd be helpful. Thank you.
I recommend you to use request.POST.get to get post data:
add_comment = request.POST.get('comment101',None)
Where None is the default value if nothing is passed. Then in the following lines you should check whether add_comment is None or not by a simple if statement:
if add_comment is not None:
#do the work
I also recommend you to control the request type with request.method == 'POST'.
Then you can create the comment:
comment = Comment()
comment.comment = add_comment;
comment.comment_date = timezone.now()
comment.entry = p
comment.save()
To debug, I personally use print keyword. If you would like to see all post data you can iterate and print them. When you use print keyword or method (for python 3) you can see the output in from ./manage.py runserver outputs.
for key, value in request.POST.iteritems():
print key, value
I would use
c = Comment(comment=add_comment, comment_date=timezone.now(), entry=p)
c.save()
That might be of some use.
Also if you want to debug code it is best to place
import pdb; pdb.set_trace()
which gives you interactive console wherever you want it.
In case you want to use something better use ipdb (pip install ipdb)
import ipdb; ipdb.set_trace()
Related
I am Building a BlogApp and I am stuck on a Problem
What i am trying to do
I am trying to access only one user which i have opened the profile online status in template. BUT it is showing all the active users.
What i am doing
I am using online_users_activity to know which user is online.I am using This django_online_users
The Problem
It is showing all the users that are online.
views.py
def online(request,user_id):
user_status = online_users.models.OnlineUserActivity.get_user_activities(timedelta(hours=87600))
users = (user for user in user_status)
context = {'users':users}
return render(request, 'online.html', context)
I don't know what to do.
Any help would be Appreciated.
You can simply annotate whether the user is online or not yourself by checking if last_activity is greater than some calculated time using Conditional Expressions:
from django.db.models import BooleanField, Case, Value, When
from django.shortcuts import get_object_or_404
from django.utils import timezone
def online(request,user_id):
min_time = timezone.now() - timedelta(hours=87600)
queryset = online_users.models.OnlineUserActivity.objects.filter(user_id=user_id).annotate(
is_online=Case(
When(last_activity__gte=min_time, then=Value(True)),
default=Value(False),
output_field=BooleanField(),
)
)
online_user_activity = get_object_or_404(queryset)
context = {'online_user_activity': online_user_activity}
return render(request, 'online.html', context)
Now the user whose profile you are checking would have an annotated field is_online so you can check as:
{% if online_user_activity.is_online %}
Online
{% else %}
Offline
{% endif %}
So basically i have a complicated scenario. I am current using Django to build a website and i have current made two apps. Both apps have almost identical fields. The field I would want to focus on though is the Information field(which they both have and which i have auto generated with the help of the Wikipedia model)
So the case here is that I want to create an if and else statement in the html in such a way that if the page i am hyperlinking to exists it would go to the link dealing with DetailView but if it doesnt exist I would redirected to the Create View
I should also note that the two apps have their names linked with the help of the foreign key but when i try to open information links using the same name , they gave me different pks
I dont feel like i explained my problem well enough but I hope someone can understand what i mean
UPDATE
ok I create the get function using
def get(self, request, *args, **kwargs):
try:
self.object = self.get_object()
except Http404:
return redirect('/create/')
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
but i dont know how to use the CreateView fuction i created instead of the link i put
This is the Detail View Html
{%extends "home.html"%}
{%block head_title%} {{block.super}}{%endblock head_title%}
{% block content%}
<!-- verify authentication -->
{% if request.user.is_authenticated%}
<h3>{{object.title}}</h3><br/>
{% endif %}
<ul type="disc">
<div class="container">
<li><b>Artist: </b>{{object.Summary}}</li>
<li><b>Genre: </b>{{object.Genre}}</li>
<li><b>Bio: </b><br>{{object.Bio}}</li>
EDIT
</div>
</ul>
{%endif%}
{% endblock %}
This is my model
from django.db import models
from django.conf import settings
from Blog.models import MainPage
from django.urls.base import reverse
from Blog.Retrieve import retriever
from django.db.models.signals import pre_save,post_save
import InfoPedia
class InfoPedia(models.Model):
user =models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
Name =models.ForeignKey(MainPage,on_delete=models.CASCADE)
Location =models.CharField(max_length= 50,null=True,blank=True)
Information =models.TextField(null=True,blank=True)
TrackListing=models.TextField(null=True,blank=True)
Published=models.BooleanField(default=True)
Timestamp=models.DateTimeField(auto_now=True)
Updated=models.DateTimeField(auto_now=True)
def get_absolute_url(self):
# return f"/Blog/{self.slug}"
return reverse('InfoPedia:DetailView', kwargs={"pk":self.pk})
class Meta:
ordering=["-Updated","-Timestamp"] #orranges in order of updated
def get_tracklist(self):
return self.TrackListing.split(",")
def Information_create_pre_save( instance, sender, **kwargs):
instance.Information=retriever(instance.Name)
def rl_post_save_reciever(sender, instance,created,*args,**kwargs):
print("saved")
print(instance.Timestamp)
pre_save.connect(Information_create_pre_save, sender=InfoPedia)
post_save.connect(rl_post_save_reciever, sender=InfoPedia)
An alternative - rather than checking the if/else in the HTML, just make all the links to the DetailView URL.
Then, in the get() handler for the DetailView, you perform a queryset lookup for the object. If no object is found, then instead of displaying the DetailView HTML, return to the user a 302 redirect (i.e. a temporary redirect) to the CreateView for that object. So all your if/else logic is in the view function or class, instead of HTML.
How can I insert data to my django database from a function in the views,py file? Is python manage.py shell the only way to insert?
For more explanations I'm using:
python 3.4
django 1.8.2
PyMySQL
For example:
models.py:
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
city = models.CharField(max_length=60)
views.py:
from django.http import HttpResponse
import pymysql
from books.models import Publisher
def send(request):
p = Publisher(name='Apress', city='Berkeley')
p.save()
urls.py
from niloofar.views import send
url(r'^index/', send),
I want when the page index is loaded, the send function works and insert data to database.
It does not work. It does not give any error and also nothing happened when i refreshed the index page, nothing was sent to database. I think there is mistake in syntax, in the way i'm trying to insert data.
Let me notice that even when I run python manage.py shell then:
from books.models import Publisher
p = Publisher(name='Apress', city='Berkeley')
p.save()
nothing will be inserted to django database.
Your question is very unclear. You should probably go through the django-tutorial.
But sure you can insert data into the db from views. Assume you have a model called Foo:
models.py
class Foo(models.Model):
name = models.CharField(max_length=100)
view.py
from .models import Foo
def some_name(request):
foo_instance = Foo.objects.create(name='test')
return render(request, 'some_name.html.html')
You can just create an instance of one of your models and save it. Suppose you have an Article model:
from django.http import HttpResponse
from django.template import loader
from .models import Article
def index(request):
article = Article()
article.title = 'This is the title'
article.contents = 'This is the content'
article.save()
template = loader.get_template('articles/index.html')
context = {
'new_article_id': article.pk,
}
return HttpResponse(template.render(context, request))
An easy way to do this would be to make use of create function. By mentioning the field name and their values. The following illustrated code helps you to insert data into your database from views.py and display the contents of database into the html page.
Suppose we have a table which looks something like this
Name Age Marks
Bunny 4 10
Tanishq 12 12
The models.py looks something like this
from django.db import models
# Create your models here.
class Student(models.Model):
student_name = models.CharField(max_length = 120)
student_age = models.IntegerField()
student_marks = models.IntegerField()
So the views.py would look something like
from django.shortcuts import render
from .models import Student # Student is the model class defined in models.py
# Assuming the data to be entered is presnet in these lists
stud_name = ['Aman', 'Vijay']
stud_age = [13, 12]
stud_marks = [20, 22]
def my_view(request, *args, **kwargs):
# Iterate through all the data items
for i in range(len(stud_name)):
# Insert in the database
Student.objects.create(Name = stud_name[i], Age = stud_age[i], Marks = stud_marks[i])
# Getting all the stuff from database
query_results = Student.objects.all();
# Creating a dictionary to pass as an argument
context = { 'query_results' : query_results }
# Returning the rendered html
return render(request, "home.html", context)
The following should be the home.html file to display all entered data
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<h1>HOME</h1>
<table>
<tr>
<th>Name</th>
<th>Age</th>
<th>Marks</th>
</tr>
{% for item in query_results %}
<tr>
<td>{{ item.student_name }}</td>
<td>{{ item.student_age }}</td>
<td>{{ item.student_marks }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
Below change required for the insert, otherwise you will get type error
Student.objects.create(stud_name = stud_name[i], stud_age = stud_age[i], stud_marks = stud_marks[i])
you may try this:
def myFunction(request):
myObj = MyObjectType()
myObj.customParameter = parameterX
...
myObj.save()
i am trying to do a simple Django application where employee list is read from database and displayed. for that i defined the models and entered the values to database through Django admin. But while trying to display data from database i am stuck with an error, "ViewDoesNotExist at /employeeProfile/ : Could not import task.employeeDetails.views. Error was: cannot import name emp_profile ".I am relatively new to django,so please help me to solve this. i will paste the code here.enter code here
VIEWS.PY
from django.shortcuts import render_to_response
from django.contrib.auth.models import*
from task.employeeDetails.models import *
from django.conf import settings
from django.http import HttpResponse
from task.employeeDetails import emp_profile
def employeeList(request):
tableList = EmployeeDetails.objects.all()
return render_to_response('employeeList.html', {'emp_list': tableList})
def employeeProfile(request):
profile = EmployeeDetails.objects.all()
return render_to_response('employeeProfile.html',{'emp_profile':emp_profile})
URLS.PY
(r'^employeeProfile/$','task.employeeDetails.views.employeeProfile'),
TEMPLATE
<html>
<body>
{%for emp in emp_profile%}
<tr> <td>{{ emp.userName }} {{ emp.designation }} {{ emp.employeeID }}</td> </tr><td>
{%endfor%}
</table></h4>
</body>
</html>
def employeeProfile(request):
profile = EmployeeDetails.objects.all()
return render_to_response('employeeProfile.html',{'emp_profile':emp_profile})
You named it profile on line 2, and then you tried to put it in the dictionary as emp_profile on line 3.
from task.employeeDetails import emp_profile
What is emp_profile and where exactly is it? from the looks of it, employeeDetails is the name of your directory, so unless emp_profile is a file in employeeDetails/, is defined in employeeDetails/__init__.py (or otherwise imported there), it will throw an import error.
I assume you want:
def employeeProfile(request): profile = EmployeeDetails.objects.all()
return render_to_response('employeeProfile.html',{'emp_profile':profile})
As Yuji pointed out, it looks like emp_profile isn't defined anywhere
I went to all the documentation, also I went to the IRC channel (BTW a great community) and they told me that is not possible to create a model and limit choices in a field where the 'current user' is in a ForeignKey.
I will try to explain this with an example:
class Project(models.Model):
name = models.CharField(max_length=100)
employees = models.ManyToManyField(Profile, limit_choices_to={'active': '1'})
class TimeWorked(models.Model):
project = models.ForeignKey(Project, limit_choices_to={'user': user})
hours = models.PositiveIntegerField()
Of course that code doesn't work because there is no 'user' object, but that was my idea and I was trying to send the object 'user' to the model to just limit the choices where the current user has projects, I don't want to see projects where I'm not in.
Thank you very much if you can help me or give me any advice, I don't want to you write all the app, just a tip how to deal with that. I have 2 days with this in my head and I can't figure it out :(
UPDATE: The solution is here: http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/ sending request.user to a model.
This limiting of choices to current user is a kind of validation that needs to happen dynamically in the request cycle, not in the static Model definition.
In other words: at the point where you are creating an instance of this model you will be in a View and at that point you will have access to the current user and can limit the choices.
Then you just need a custom ModelForm to pass in the request.user to, see the example here:
http://collingrady.wordpress.com/2008/07/24/useful-form-tricks-in-django/
from datetime import datetime, timedelta
from django import forms
from mysite.models import Project, TimeWorked
class TimeWorkedForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super(ProjectForm, self).__init__(*args, **kwargs)
self.fields['project'].queryset = Project.objects.filter(user=user)
class Meta:
model = TimeWorked
then in your view:
def time_worked(request):
form = TimeWorkedForm(request.user, request.POST or None)
if form.is_valid():
obj = form.save()
# redirect somewhere
return render_to_response('time_worked.html', {'form': form})
Model itself doesn't know anything about current user but you can give this user in a view to the form which operates models objects (and in form reset choices for necessary field).
If you need this on admin site - you can try raw_id_admin along with django-granular-permissions (http://code.google.com/p/django-granular-permissions/ but I couldn't rapidly get it working on my django but it seems to be fresh enough for 1.0 so...).
At last, if you heavily need a selectbox in admin - then you'll need to hack django.contrib.admin itself.
Using class-based generic Views in Django 1.8.x / Python 2.7.x, here is what my colleagues and I came up with:
In models.py:
# ...
class Proposal(models.Model):
# ...
# Soft foreign key reference to customer
customer_id = models.PositiveIntegerField()
# ...
In forms.py:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.forms import ModelForm, ChoiceField, Select
from django import forms
from django.forms.utils import ErrorList
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
from .models import Proposal
from account.models import User
from customers.models import customer
def get_customers_by_user(curUser=None):
customerSet = None
# Users with userType '1' or '2' are superusers; they should be able to see
# all the customers regardless. Users with userType '3' or '4' are limited
# users; they should only be able to see the customers associated with them
# in the customized user admin.
#
# (I know, that's probably a terrible system, but it's one that I
# inherited, and am keeping for now.)
if curUser and (curUser.userType in ['1', '2']):
customerSet = customer.objects.all().order_by('company_name')
elif curUser:
customerSet = curUser.customers.all().order_by('company_name')
else:
customerSet = customer.objects.all().order_by('company_name')
return customerSet
def get_customer_choices(customerSet):
retVal = []
for customer in customerSet:
retVal.append((customer.customer_number, '%d: %s' % (customer.customer_number, customer.company_name)))
return tuple(retVal)
class CustomerFilterTestForm(ModelForm):
class Meta:
model = Proposal
fields = ['customer_id']
def __init__(self, user=None, *args, **kwargs):
super(CustomerFilterTestForm, self).__init__(*args, **kwargs)
self.fields['customer_id'].widget = Select(choices=get_customer_choices(get_customers_by_user(user)))
# ...
In views.py:
# ...
class CustomerFilterTestView(generic.UpdateView):
model = Proposal
form_class = CustomerFilterTestForm
template_name = 'proposals/customer_filter_test.html'
context_object_name = 'my_context'
success_url = "/proposals/"
def get_form_kwargs(self):
kwargs = super(CustomerFilterTestView, self).get_form_kwargs()
kwargs.update({
'user': self.request.user,
})
return kwargs
In templates/proposals/customer_filter_test.html:
{% extends "base/base.html" %}
{% block title_block %}
<title>Customer Filter Test</title>
{% endblock title_block %}
{% block header_add %}
<style>
label {
min-width: 300px;
}
</style>
{% endblock header_add %}
{% block content_body %}
<form action="" method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Save" class="btn btn-default" />
</form>
{% endblock content_body %}
I'm not sure that I fully understand exactly what you want to do, but I think that there's a good chance that you'll get at least part the way there using a custom Manager. In particular, don't try to define your models with restrictions to the current user, but create a manager that only returns objects that match the current user.
Hmmm, I don't fully understand your question. But if you can't do it when you declare the model maybe you can achieve the same thing with overriding methods of the class of objects where you "send" the user object, maybe start with the constructor.
Use threadlocals if you want to get current user that edits this model. Threadlocals middleware puts current user into process-wide variable. Take this middleware
from threading import local
_thread_locals = local()
def get_current_user():
return getattr(getattr(_thread_locals, 'user', None),'id',None)
class ThreadLocals(object):
"""Middleware that gets various objects from the
request object and saves them in thread local storage."""
def process_request(self, request):
_thread_locals.user = getattr(request, 'user', None)
Check the documentation on how to use middleware classes. Then anywhere in code you can call
user = threadlocals.get_current_user