How to insert data to django database from views.py file? - python

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()

Related

'NoneType' object has no attribute 'DoesNotExist'

I would appreciate some help in receiving data from a database by viewing it in another page as you click onto the search button. The problem I am receiving is an AttributeError. after clicking into that button
I have tried to look at similar issues.
Views.py
def act_results(request):
'''
display the acts suitable for a particular user
'''
template = loader.get_template('polls/act_results.html')
try:
Act = request.GET.get('Act')
data = Act.objects.get(act__name=Act)
return HttpResponse(template.render({'Act':Act},request))
except Act.DoesNotExist:
return HttpResponse(template.render({'error_msg':'Act does not exist for this Festival'}))
models.py
class Act(models.Model):
name = models.CharField(primary_key=True,max_length=100)
stage = models.CharField(max_length=100)
start_time = models.TimeField()
end_time = models.TimeField()
date = models.DateTimeField()
def __str__(self):
return self.name
act_results.html
<table style="width:100%">
<tr>
<th>Acts available</th>
</tr>
<tr>
<td>Act : {{ Acts }}</td>
</tr>
</table>
{% endif %}
I expect to receive all the information about that act in the html page.
As of now I am receiving an error.
You've overwritten the name Act by assigning it to the result of the request.GET.get() call. Use a different name there.
Also you should be passing the result of the db lookup, not the request item, to the context. And template.render doesn't take the request as a second parameter. You should be using the standalone render shortcut anyway.
from django.shortcuts import render
...
def act_results(request):
value = request.GET.get('Act')
try:
item = Act.objects.get(act__name=value)
context = {'Act': item}
except Act.DoesNotExist:
context = {'error_msg':'Act does not exist for this Festival'}
return render(request, 'polls/act_results.html', context)
I don't know what the CSV has to do with anything, though. And the lookup filter is suspect; does your Act model have a relationship with another model via an act field? Seems unlikely. And your template should have {{ Act }}, not {{ Acts }}.
Honestly, the summary here is that you really need to take more care with your code.

Django CMS custom plugin load data from cms_title

I want to create a custom plugin for Django CMS. As the guide was showing, I created some examples. But now the goal is to create a plugin that will get the data from (mysql) database. It will load all titles that belong to the menu, because I want to have some similar to table of contents.
To get data from an custom model, the code goes like this:
models.py:
from cms.models.pluginmodel import CMSPlugin
from django.db import models
class Hello(CMSPlugin):
guest_name = models.CharField(max_length=50, default='Guest')
cms_plugins.py:
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from django.utils.translation import ugettext_lazy as _
from .models import Hello
class HelloPlugin(CMSPluginBase):
model = Hello
name = _("Hello Plugin")
render_template = "hello_plugin.html"
cache = False
def render(self, context, instance, placeholder):
context = super(HelloPlugin, self).render(context, instance, placeholder)
return context
plugin_pool.register_plugin(HelloPlugin)
But as cms_title belongs to the Django-CMS by default, what options are possible here? Where can I find the definition of CMS model with name Title? Would setting it to CMSPlugin instance be a bad way?
Well, after few hours of struggling with this case, I finally succeeded to resolve my problem.
First of all, to answer the part of the question with CMS model and parameter title (in db: cms_title). Creating a new model with the FK to CMS title is the right way.
In models.py:
class TitlePlugin(CMSPlugin):
title = models.ForeignKey(Title)
As next, you need to import it to cms_plugins.py, so it will look like this:
from .models import TitlePlugin
class MyTitlePluginClass(CMSPluginBase):
model = TitlePlugin
render_template = "titles.html"
cache = False
As you see, the model that we load is TitlePlugin, we defined in models.py (which has FK to original cms_title).
And now, render it:
def render(self, context, instance, placeholder):
context = super(MyTitlePluginClass, self).render(context, instance, placeholder)
return context
But my goal was to load it into template for the purpose of 'table of contents', right? So I had to change some things.
I removed models.py content (not needed!)
The new cms_plugins.py had modifications too:
first:
from cms.models.pagemodel import Page
#we import the Page model
and the renewed class:
class MyTitlePluginClass(CMSPluginBase):
model = CMSPlugin
render_template = "titles.html"
cache = False
def render(self, context, instance, placeholder):
pages = Page.objects.filter(in_navigation=True, publisher_is_draft=False)
#context = {
#'pages' : pages,
#}
# edit: append to 'pages' existing list!
context['pages'] = pages
context = super(MyTitlePluginClass, self).render(context, instance, placeholder)
return context
plugin_pool.register_plugin(MyTitlePluginClass)
And in the template, we simply print it using for loop
titles.html:
{% for page in pages %}
<div class="panel callout ">
{{ page }}
</div>
{% endfor %}

How do I get POST data from a free text field?

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()

ViewDoesNotExist Error

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

Model limit_choices_to={'user': user}

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

Categories

Resources