Currently, I am writing up a bit of a product-based CMS as my first project.
Here is my question. How can I add additional data (products) to my Product model?
I have added '/admin/products/add' to my urls.py, but I don't really know where to go from there. How would i build both my view and my template? Please keep in mind that I don't really know all that much Python, and i am very new to Django
How can I do this all without using this existing django admin interface.
You will want to wire your URL to the Django create_object generic view, and pass it either "model" (the model you want to create) or "form_class" (a customized ModelForm class). There are a number of other arguments you can also pass to override default behaviors.
Sample URLconf for the simplest case:
from django.conf.urls.defaults import *
from django.views.generic.create_update import create_object
from my_products_app.models import Product
urlpatterns = patterns('',
url(r'^admin/products/add/$', create_object, {'model': Product}))
Your template will get the context variable "form", which you just need to wrap in a <form> tag and add a submit button. The simplest working template (by default should go in "my_products_app/product_form.html"):
<form action="." method="POST">
{{ form }}
<input type="submit" name="submit" value="add">
</form>
Note that your Product model must have a get_absolute_url method, or else you must pass in the post_save_redirect parameter to the view. Otherwise it won't know where to redirect to after save.
This topic is covered in Django tutorials.
Follow the Django tutorial for setting up the "admin" part of an application. This will allow you to modify your database.
Django Admin Setup
Alternatively, you can just connect directly to the database using the standard tools for whatever database type you are using.
Related
i create a model for website/ frontend . i have 3 types of users. only 1 type i want to see the frontend model. how to create a dynamic access control for the django frontends. please give some solutuion or suggest a plugin. Thanks for solution in advance.
You can do this on the template or views side.
Assuming your preferred user type is 'student', you do this:
Template
{% if user.is_authenticated and user.is_student %}
*content*
{% endif %}
Or this:
Views
Assuming you want to restrict the details of a blog post to only students, you need to create a condition right after defining the 'post_detail_view' view function.
def post_detail_view(request):
if not request.user.is_student:
**do something (eg. raise 404 or httpresponse or redirect)**
**code for this view goes here**
Declaring the restriction in the view allows you to do more than just restrict the content. You can raise a 404 error, redirect the unauthorized user and more. The template solution simply lets you restrict the content.
I hope this solves your problem.
Is there a way to prevent users from accessing some (or all) URLs in application? For example, I am following Django tutorial and one of the examples has a URL:
#music/album/<pk>/delete
url(r'image/(?P<pk>[0-9]+)/delete/$', views.ImageDelete.as_view(), name='image-delete'),
that deletes database entry give pk as a parameter. Of course, now it is possible to delete this entry with just copy-pasting the URL with any existing primary-key, so what is the best practice to avoid it? Thanks
EDIT. Based on the replies and comments, I decided to elaborate a bit more. I am actually using DeleteView and forms with POST request as #solarissmoke suggested in answer.
<form action="{% url 'album:image-delete' image.id%}" method="post" style="display: inline;">
{% csrf_token %}
<input type="hidden" name="image_id" value="{{ image.id }}"/>
<button type="submit" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-trash"></span>
</button>
</form>
and in my views.py:
class ImageDelete(DeleteView):
model = Album
# if you successfully delete the object, page redirects to <homepage>
success_url = reverse_lazy('album:index')
So, there were few suggestions on checkin whether the user is verified to delete URL entry (e.x. the image) and to add pop up/notification to verify if the user indeed wants to delete the entry. However, it does not feel like a complete solution. In the comments I brought example of Facebook, where you can not delete imeage/post by just copy-pasting the delete URL. Surely I'm not asking for Facebook-like security, however, I'm really curious how can secure URLs so that it's nearly impossible for regular user to delete entry with simple copy-pasting. Thanks again!
Best practice is that you should not be allowing modification of data like this through HTTP GET requests, which are intended (as the name suggests) for getting data rather than updating it.
You should use forms and POST requests to perform actions like deleting objects etc. Django provides lots of helper views for doing this. For example DeleteView:
A view that displays a confirmation page and deletes an existing object. The given object will only be deleted if the request method is POST. If this view is fetched via GET, it will display a confirmation page that should contain a form that POSTs to the same URL.
The advantages of using these views are:
You can make sure the user has permissions to edit an object before making any changes. Django will perform the basic checks (e.g., CSRF) for you. You can augment the views to perform additional checks like making sure a user is logged in or checking any other permission.
You can enforce Cross-Site Request Forgery Protection.
It is not possible to accidentally delete an object by visiting a URL a second time (as the documentation above explains).
there are many ways.. e.g:
user = request.user
if user.is_authenticated() and user.profile.can_delete_image(image_pk):
# only then, image can be deleted by this user
# can_delete_image(image_pk) is defined by you
else:
raise DeletePermissionDenied # you can define your own Exception, just for fun
Duplicate question to Django-Taggit in Edit Form. However, the answer doesn't work for me.
I'm using Django Taggit in a form. The form is populated by an instance of an object that has Django Taggit enabled.
In my template, the forms tag input field value is set like so:
value="{{ form.tags.value|default_if_none:"" }}"
This results in a string value in the rough format of:
value="[<TaggedItem: foo tagged with bar>]"
If I render the form using basic Django form rendering ( i.e. {{form}} ), the tag field value is rendered correctly ( i.e. "tag1, tag2" ). Strangely, this is the opposite to what the poster of Django-Taggit in Edit Form was experiencing. For them, {{ form }} wasn't rendering the value correctly, but for me, it is.
Why is there this difference between my form and Django's? How can I make the tag value render correctly in my custom form template?
I have a solution that feels hacky but works.
When instantiating the form, modify the initial state for the tags:
form = YourModelForm(request.POST or None, instance=your_model_instance, initial={
'tags' : edit_string_for_tags(your_model_instance.tags.get_query_set())
})
edit_string_for_tags() and get_query_set() are part of Django Taggit.
Note: You'll need to import edit_string_for_tags(). i.e. from taggit.utils import edit_string_for_tags
I'm having a really confusing issue with some views in Django. I created Update and Create views, both using the generic versions, both using the same template. They worked perfectly...until I added a custom modelForm to exclude a field. Now, the Create view still works correctly, but the Update view won't render a form at all.
Form:
class member_form(ModelForm):
class Meta:
model=member
exclude=('created_by',)
Views:
class member_detail(generic.UpdateView):
form_class=member_form
model=member
template_name_suffix='_detail'
class member_create(generic.CreateView):
form_class=member_form
model=member
template_name_suffix='_detail'
Urls (main):
url(r'^members/',include(members.urls',namespace=members),name='members_list'),
Urls (app):
url(r'^$',login_required(views.member_list.as_view()),name='index'),
url(r'^(?P<pk>\d+)/$',login_required(views.member_detail.as_view(success_url=".")),name='detail'),
url(r'^new/$',permission_required('members.add_member')(views.member_create.as_view(success_url='/members/')),name='create'),
This worked perfectly for both views until I added the form_class. Now, member_create still works perfectly, but member_detail shows nothing for {{ form.as_table }}. When I switch it to just {{ form }} in that template, I get this for member_detail:
<members.views.member_form object at 0x7f7de3f20d50>
What's going on here? Any ideas? Thanks!
The problem was a stupid naming mistake on my part, on the production code, which I found while trying to redact new sections to add to the question; the _create and _form objects in my question were both named _form in production.
I have a custom Contact Form App, and I want to integrate it with django-cms. From what I understand I have to register the app with django-cms, and then in my views I have to return a RequestContext instance instead of a regular context instance. So in my views.py, I have
return render_to_response('my_template.html',
{'form': form},
context_instance=RequestContext(request))
I don't know if I'm missing something here, but my issue here is that I don't want to hardcode the template name my_template.html. Instead, I want the template to be the same one I put when adding a new page, so my question is, is there a way to get the template from the django-cms page thats hosting the app or do I have to hardcode the template to be used?
If your apphook is a single view mounted on /, you can just use {% extends request.current_page.get_template %}, however this does not work on subpages in your app.
For that you would need to reverse the root view of your app, use cms.utils.page_resolver.get_page_from_request with the use_path argument to get the page, then call get_template on the page and extend that.