I'm using Django as backend and Yeoman as frontend. I'm new to both. My frontend local server is running on localhost:9000, and my backend server is running on localhost:8000.
I just built an email sender application following the Django tutorial. It is working perfectly and consists of:
A form:
class ContactForm(forms.Form):
name = forms.CharField()
email = forms.EmailField()
telephoneNr = forms.IntegerField()
message = forms.CharField(widget=forms.Textarea)
A view:
from django.core.mail import send_mail
from django.shortcuts import render, render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from mailsender.forms import ContactForm
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
success = True
name = form.cleaned_data['name']
email = form.cleaned_data['email']
telephoneNr = form.cleaned_data['tlf']
message= form.cleaned_data['melding']
receiverEmail = ['somewhere#example.com']
text = message +'\n'+name +'\n'+str(telephoneNr)
send_mail('Contact form', beskjed, email, receiverEmail)
return render(request,"result.html")
else:
form = ContactForm(
return render(request, 'contactform.html', {'form':form})
And my HTML:
<h1>Contact us</h1>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">
<table>
{{ form.as_p }}
</table>
{% csrf_token %}
<input type="submit" value="Submit">
</form>
If I visit localhost:8000/contactform, the contact form is displayed just as I want, and it does send emails.
I need help figuring out how to hook up this view to the Yeoman frontend - as searching the Internetz (and SO) leads me to the path of confusion. Should I use Tastypie? I really want to keep this logic in the backend. Any help pointing me in the right direction is greatly appreciated.
First off, you should consider not using Django templates & forms at all. (Supposing you're working on some bigger stuff)
Django is a really cool framework, but I found those 2 building blocks of it somewhat limited (https://stackoverflow.com/a/17383408/1432478).
The JS framework, that you use with Yeoman should take care of building HTML.
Django-Yeoman integration
Development architecture
Yeoman should serve html (templates replacement) and other static files + take care of JS framework of your choice.
If frontend needs to obtain/submit some data from/to the backend, it should issue a request to the very same server that is serving static content (Under the bonnet Yeoman is using Node.js as this server).
But wait ... how Node.js server is supposed to know about backend logic?
Yo can use grunt-connect-proxy to forward any request to another server - in this case Django.
I found this grunt-connect-proxy setup guide particularly helpful.
By issuing backend requests to the very same socket address (IP:port), you don't have to perform CORS or crazy stuff like parsing whole of your frontend code when building the production-ready version of your app in order to replace the socket address used in development with the one suitable for production.
Production & Deployment
When you run grunt it'll package production-ready version of your frontend static files in dist subdirectory.
Before submitting your django application as a package you basically copy htmls and the rest of the static content files to static/your_app.
I decided to serve Angular's htmls as static content - making them Django's templates would cause too much fuss (conflicting markup, static loaders, and so on ...).
When some django project (containing your django app) is deployed, the static files, that were in dev setup served by node, are going to be served by django.
In other words: in production you need only one server - the one used by django.
It's only during development, that you need to benefit from fuzzy-buzzy stuff offered by yeoman, such as:
LiveReload
linting your code
generators
...
Note: I've read that Yeoman team is planning on providing a better way of integrating yeoman with web frameworks. Not sure how they want to do it, perhaps a similar solution to generators (separate generator per framework).
Sample
Yo can check out a django app I'm currently working on: https://github.com/vucalur/django-wibses/
It uses Angular JS and above I just described the architecture of it :)
Note: It is so not-finished-yet :) But as of today development setup is done, except for CSRF protection.
Tastypie
We are considering using Tastypie in the mentioned app, but only when writing RESTful API manually will become arduous. So I think whether to use Tastypie or not is up to you.
Further reading
I based my setup on this.
But if you know something about Java web apps, you should take a look at those (I wanted my Django-Yeoman integration work similarly to how Java(Maven)-Yeoman integration works):
http://addyosmani.com/blog/making-maven-grunt/
https://github.com/trecloux/yeoman-maven-plugin (mentioned in Addy's post)
http://blog.tartachuc.org/2013/06/11/tomcat-maven-angular-grunt-et-yeoman-sont-dans-un-bateau/ (mentioned in Addy's post)
http://naleid.com/blog/2013/01/24/calling-gruntjs-tasks-from-gradle/
http://blog.tfnico.com/2013/07/considerations-for-javascript-in-modern.html (not directly related, but still worth reading)
Related
I have created a working Django application. I am using django-allauth for implementing social-account authentication.
Now, suppose I am logged-in inside my application using an e-mail id whose user does not have a staff access and, if I open admin login page directly, the admin login page is displayed as follows:
My question is: how can I stop Django from displaying the message "Successfully signed in as ... "? Where is the source of this message present?
The Successfully signed in message is a message from django-allauth. It uses the messages framework.
I suggest that you add the template code to display messages to your base template. That way, the message will be displayed immediately after you have logged in, rather than when you go directly to the admin login (which does include the template code to display messages).
The text you are referring to (You are authenticated as ...) can be found in this template:
python3.6/site-packages/django/contrib/admin/templates/admin/login.html
You can override this template to remove the messsage. For example, look into this question for how to override djangos default templates.
To override this you need to inherit the template by {% extends "admin/login.html" %}
Then you need to override the block with the name.
{% blocktrans trimmed %} You are authenticated as {{ username }}, but are not authorized to access this page. Would you like to login to a different account? {% endblocktrans %}
Now you can customize this particular line and then point your function to load your custom html file instead of the standard admin ones or you can directly edit the login.html in your django package(Not a good idea). To know where it is fetching from you can do the following...
$python
>>>import sys
>>>sys.path = sys.path[1:]
>>>import django
>>>print(django.__path__)
And then go into contrib\admin\templates\admin and edit the login.html manually.
The installation page looked simple enough. I installed it, added easy_select2 in INSTALLED_APPS in the settings, ran collectstatic, and then had this in my form:
from easy_select2 import Select2Multiple
# from django_select2 import forms as select2_forms
class LeadForm(forms.Form):
email = forms.CharField(max_length=100)
overseas_company = forms.MultipleChoiceField(
choices=countries,
label='Do you have any companies overseas and where?',
widget=Select2Multiple()
)
But it still renders as if I had done nothing at all. I tried django_select2 as well, and it didn't work either, so I must be doing something wrong Select2 wise.
I tried looking at the HTTP request log. Merely enabling easy_select2 doesn't make the template request the jQuery/select2 js files that are needed for the Select2 widget to function. Is this the problem? But the tutorial never said I had to add anything to any existing templates.
I had the same problem too.
You have to add {{ form.media }} in the head section of your template for django to make it work.
source: http://do-it-big.com/getting-django-easy-select2-to-include-jquery-and-friends/
What I've already done
I have a frontend entirely built with React.JS.
All the business logic is handled by Django and exposed by Django REST Framework via an API.
I'm able to build for different mobile environnements (Android and iOS via Cordova)
The web application is accessible via my Django project (the same that exposes the api), the frontend is sill the same ReactJS code bundled via webpack.
The App has a single entry point, main.js which is a bundled version of my react.js components and dependencies, so my index.html typically looks like this :
<body>
<script type="text/javascript" src="/static/bundles/main-3997ad3476694c3c91cf.js"></script>
</body>
What I want to do
I want to provide a server-side rendering of my web application to let web crawlers correctly index my app on web (I'm not looking for server-side rendering for mobile builds)
How can I handle this considering the fact that my app is a Single Page Application ? I do not want to reinvent the wheel nor to duplicate my code. What kind of node.js server do I have to write in order to achieve this automatic server-side rendering ? Is there any way to provide the server side rendering directly in Django (via some tools reading and interpreting the final results of the page as displayed on the client-side and returning this raw html ?)
You have probably solved your problem by now, but I wanted to share my solution for this.
I have a very similar setup, and have something that seems to work pretty well so far. I basically have a django w/ DRF backend api and isomorphic React/Flux javascript app. I also run a node server next to the python backend server, which acts only as a 'template rendering' service. In essence, replacing the django render function.
So I simply replace the django View with a special IsoView which calls off via http to the node server and returns the rendered html.
from rest_framework.renderers import JSONRenderer
import requests
class IsoView(View):
def user_json(self):
if self.request.user.is_anonymous():
return {'anonymous': True}
else:
return UserSerializer(self.request.user, context={'request': self.request}).data
#classmethod
def render(cls, request, template, data):
req_data = JSONRenderer().render(data)
try:
headers = {'content-type': 'application/json'}
query_params = request.GET
resp = requests.post(_build_url(request.path), params=query_params, data=req_data, headers=headers, timeout=0.1)
reply = resp.json()
if resp.status_code == 302:
return redirect(reply.get('redirect'))
if 'error' in reply:
raise Exception("\n\nRemote traceback: {}".format(reply.get('traceback')))
except requests.exceptions.RequestException as err:
logger.warn('IsoView request exception: {}'.format(err))
reply = {}
return render(request, template, {
'react': reply.get('result'),
'data': data
})
And use it like so:
class HomePage(IsoView):
def get(self, request, *args, **kwargs):
return self.render(request, 'app.html', {
'user': json_data...
})
This also assumes a django template which uses something like this
<html>
<head>
<script>
window.data = {{ data|json }};
</script>
</head>
<body>{{ react|safe }}</body>
</html>
What this does is it renders the html returned from node in the body tag and also dumps the json data required for bootstrapping the app on the client in the window.data object.
This is a really simplified version of the system, but it should work. You should be careful with XSS attacks on the window.data bit, so make sure to escape all your json data but other than that, you should be all good.
Then the node template server looks really similar to any of the tutorials online that you can find for server-side react. Just a simple express app.
Alternatively, you don't need to mess around with django templates at all if you render the full ... in node and return that as a string.
Hope that helps.
The situation is simply that we want to send information to Django (our web framework), have it perform functions on the information, and receive information back from Django.
Just now our form to POST to the server looks like this.
<form method="post" onAction="/write" name="form1">
{% csrf_token %}
<button type="submit">Send Info for processing</button>
</form>
And we want this process to send a variable or transmit information.
This successfully reaches our views.py and gets to a function where information can be done.
But currently we don't know how to take information in from the POST nor how to send it back without loading a whole new page.
Since you don't want to refresh the page when you are posting a request, you would want to make a Asynchronous Request to the Server. JQuery, Javascript library has some neat functions which would help you make an asynchronous request. After the server receives the request, it can perform computation can send an HttpResponse with HTML, XML or JSON data as mentioned by Brandon
This is a wiki page for the Tutorial on Ajax with Django
https://code.djangoproject.com/wiki/AJAX
You need to return an HttpResponse. It's up to you whether or not to return XML, JSON, HTML, etc. Your request has to be made via Ajax.
https://docs.djangoproject.com/en/1.4/ref/request-response/#django.http.HttpResponse
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.