A long introduction and installing an UI library with Tailwindcss
A good website design is already half the battle. After all, if you think about it, only its work is visible. All the work that happens on the screen is not important for the end user. What is important is that in the end this work turned out to be completely useful for him, and on this functional site it was easy to read and was not an eyesore.
After reading this article you will get something like this.
Desktop version
Mobile version
I know from my own experience that design is a must-have these days. And for a developer, it is also important how to do this design and improve it. And I will tell you, my dear reader, do it with pure JS and CSS; this is quite a task.
Take this site, for example. It is written with pure JS (okay, also jQuery) and CSS. Supporting it is a real pain; adding some new component (like image zoom; I still haven’t done it) is a real feat.
Therefore, in this project (SearchResultParser), I will use a ready-made user interface library. I will use MaterialUI + Tailwindcss for more flexible customization of the site style without the need to get into CSS files. And we will use the Axios library for communication with the server.
Let’s install them:
The TailewindCSS library needs to be configured. This command will create a configuration file:
In a Frontend/tailwind.config.js, insert the next lines of code.
It describes which files to apply this extension to.
Also, don't forget to create an input and output file. In my case, the first one is called index.css, and the other one is zero.css. The first one is in the Frontend/src directory, the other one is in Frontend/static/css. In the input file, it is enough to insert several directives:
And now, for the styles to be applied, you need to run the following command every time you change the files in which you use tailwindcss, whether it's html or js. You can add --watch so you don't have to restart it every time.
TailwindCSS is installed and configured. Now let's configure axios. Everything is pretty simple here; add the following line to the Frontend/package.json file:
Setting up django routes and views
I'll say right away that I won't have many routes. Because this site is primarily an application, they are also called SAAS. My SAAS will have the following routes/views:
main: The main application page. The user will spend most of the time here.
about: The page where I will tell about this project
contacts: The page with contact information
That's all, actually. Now let's add these views and routes to them.Let's add routes to Frontend/urls.py:
Let's write views, just for the sake of it, so that Django doesn't complain:
This is our base. We will not return to django in this article. We will layout, layout and layout again.
Developing a base website layout
Preparation for work, launching the server
To start developing and see the results of our work, you will need to run several commands in the terminal. Firstly, so that TailwindCSS can generate styles for us. Secondly, so that React has time to collect components and render them.
To generate CSS styles using tailwindcss:
Flag -i for an input file
Flat -o for an output file
You also need to specify the --watch argument so you don't have to run this command every time you change a template or script. To compile and generate JS:
Here, we run the previously recorded script in Frontend/package.json. Of course, you can do it without a script, like this:
All that remains is to launch the Django server, open a tab and start writing code.
Working with django templates
Let's create a base template, base.html in Frontend/templates/Frontend. Open it in a text editor and paste the following code:
First, we load the value of the global variable static to have access to CSS, JS, JPEG, PNG, SVG and other media files on our server.
This file, as I call them, bases, these templates are not rendered directly, their main role is to be a skeleton/foundation/base for other templates. For example, this site, where this article is hosted, has the following bases:
base.html (Basic/common interface)
base_post.html (A base for any posts on website)
base_article.html (A base for posts of article type)
base_post_list.html (A base for pagination of any posts)
And so that the template that inherits the base could modernize it and add something of its own, special blocks need to be added. In this base there are 4 of them:
head (For meta tags, styles and scripts to start in a beginning)
header (For modification of base menu)
main (For content)
scripts (Only for scripts in the end of document)
All of the above block looks and used in django templates like this:
Now that we have figured out how this template works, we need to make sure that this template is inherited by the following templates:
about.html
contacts.html
app.html
The app.html template:
The about.html template:
The template for contacts.html is identical to the template written above, with the only difference being that they have different titles, canonical address and description.
You can't live on templates alone, you need React. And you need to use it carefully. What's the matter? You might have noticed that I have special elements with IDs header and footer and next to them their analogs, meta-header and meta-footer. Why did I do this? Why not render everything in one block via react?
The reason for this is how react and django render pages. If react gives rendering to the user's machine CSR, then django does it itself, on the server SSR. So what? What difference does it make who renders what. The main thing is that they render.
There is a difference, after all. And it is especially noticeable for search engines. A search robot, a crawler, will go to a page rendered by Django and will be able to see all the links and content of the site. But if the same crawler goes to a page rendered by React, it will see nothing, will consider the page either useless or unfinished and will leave. That is, for SEO this is critical
And that's why I have these meta-* elements. They are rendered by django and are available to search engines. React picks up and processes these elements. Now that we're done with HTML, let's move on to JS and React code.
Working with React elements
Let's create the necessary elements and files. We'll need 4 of them:
Header.js (hat and website’s menu)
Footer.js
MobileAppBar.js (a menu and a hat only for the mobile version of the website)
LangSwitch.js (language switcher)
Let's start with the most complex element of our site, header.js, this is its header. The code is quite voluminous, but in essence it takes the information rendered by django and forms either horizontal (Desktop version) or vertical (Mobile version) buttons from it. That's all.
Well, if this is a mobile version, it wraps these buttons in a side menu. Because I like it the most. And here is the code:
In this component I’m using two more, LangSwitch and MenuAppBar. In the MobileAppBar.js file:
In the LangSwitch.js file:
The LangSwitch component is not that big. Most of the space is taken up by the SVG image settings. It is not working now, though, i.e. it does not switch languages. But that is because we have not yet configured django for this. This will be in the future. For now, we just have a working switch.
All that remains is to consider the Footer component in Footer.js:
Initially, I planned to add lots and lots of links there, but I got lazy, and why would there be links there? Only an extra burden on the user's perception. So I left only one link to myself)
And of course, don't forget to connect our Header and Footer components to index.js:
Developing the main page and its components
The user experience with the application
So, we are moving on to the hardest part of this article. At least, it is the biggest one. I even thought about splitting this article, but I did not do it because of the loss of integrity of article. What will the user experience with the application look like?
A random user open the website.
Click on an add button.
Selects the required engines.
Fill the text fields.
Configures the parser.
Launches it.
As a result of the work, the user will receive a link to the downloadable file.
Django application template, app.html
Now to the application and code. Let's change the app.html template a little bit so that it can be easily worked from a react component.
From the template, you can see that my application is divided into several independent parts. These are settings (id = "app_settings"), a table of queries and engines (id = "engines" + id = "queries"), utilities (id = "app_utils") and actions (id = "app_actions").
I want to note the meta-engines block. Here I manually wrote all the engines that I am going to parse, but in the future this block will be filled by django. It's just that in the future I might want to add other engines or remove old ones and it is better to do this on the server.
React components of the application
The application is divided into 4 parts + two more components:
AppSettings.js
AppUtils.js
AppActions.js
AppQueries.js
Waiter.js
Msg.js
Create them in a src/components folder and let's move on to their analysis.
AppSettings.js component. This is just a group of switches with check boxes for configuring the parser. It should be noted that the selected data is saved in the so-called data attribute. So that you can easily get them from another application, AppActions.
AppUtils.js component. This component is implemented using this chain of actions/uis, button→bottom slider→modal window. And at each stage, requests will be made to the server to get the necessary presets.
AppActions.js component. Consists of only two buttons, saving the preset and starting the parsing. Here, we collect data from other applications, here we check them for correctness and here we send them to the server.
AppQueries.js component. Getting engines available for parsing and creating an engine-query table. Initially, I planned to do it in such a way that the user would add an engine, then add as many queries to it as he wanted. But then I realized that all this can be implemented much more simply and through one button.
And also, you will need icons for all engines. You will need to download this archive and unpack it in the Frontend/static/img folder
Waiter.js component. It exists only to show the user that the server is currently busy and needs to wait a bit. It also controls the display of messages about success or failure when the server is running.
Msg.js component. This file is used to prepare (draw) a certain block to be filled with information about the results of the server's work. It is controlled via the Waiter component.
All that remains is to connect all these components to index.js:
Other pages and website’s sections.
I won't cover pages like about and contacts in such detail. Why?
These are general (I would even say standard) pages. And basically they will be static, there will be no react. They do not affect the main functionality of the site in any way. And simply, what's the point of showing what I wrote there? Or what's more important, what to tell? What font do I use, or what indents do I make?) That's it.
Conclusions
In this article, I told and showed how you can make the frontend part of the site using React and Django + MaterialUI, so as not to reinvent the wheel. TailwindCSS, to gain maximum flexibility in styling page elements (okay, so as not to get into CSS files :)).
In general, the frontend has always been the hardest part of development for me, well, it's not my thing. Making something functional and working - yes, I can do that. But making it beautiful and stylish - that's where I end.
You probably know this analogy of the frontend and the backend.
Well, for me, it's the opposite. In any case, we're done with the hardest part, and it will only get easier. We'll add an interactive tutorial, support for several languages, a backend in the end, and user authentication.
If you skipped all of the above and just want a ready-to-use solution, here it is. An archive with preconfigured folder structure and precalculated dependencies. All you need to do is set up a virtual environment (install all required Python packages) for the downloaded folder and install the required NPM packages in the Frontend app.
In this article, you will know the way to integrate the React framework into a Django project. As a result, you will get a full-stack app/website. Also in the article, …
In this article you will understand how to add a web tutorial on a website for guests using React components. With the ability to define to which elements hints will …
In this article I will describe the process of integrating allauth into a Django project. Frontend is handled by React. I will configure a registration and an authorization process by …
In this article, I will tell and show how you can deploy a site written in Django on servers from the hosting provider Reg.ru. Also from this article, you will …
Used termins
Django template ⟶ This is a text document marked up with a special syntax for inserting new code.
Django model ⟶ Is a database manager used in the Django framework. Implemented via classes and inheritance in python.
TailwindCSS framework ⟶ It is a utility-first CSS framework that streamlines web development by providing a set of pre-designed utility classes. These classes enable rapid styling without writing custom CSS, promoting consistency and scalability. Tailwind’s approach shifts focus from traditional CSS components to functional classes, empowering developers.
React ⟶ An open-source JavaScript library developed by Facebook for building user interfaces, particularly for single-page applications where you need a fast and interactive user experience. It allows developers to create reusable UI components, manage the state of their applications, and efficiently update the user interface in response to data changes.
React component ⟶ A reusable piece of code in a React application that represents a part of the user interface (UI). Components can be either class-based or functional, and they allow developers to build complex UIs by breaking them down into smaller, manageable pieces.
Related questions
What are the basic principles of OOP?
The basic principles of OOP include abstraction - the separation of a concept from its instance, polymorphism - the implementation of the same idea in different ways, inheritance - the ability of an object or class to be based on another object or class.
How can I disable the ripple effect globally?
The ripple effect is exclusively coming from the BaseButton component. You can disable the ripple effect globally by providing the corresponding value in your theme.
How can I disable transitions globally?
Material UI uses the same theme helper for creating all its transitions. Therefore you can disable all transitions by overriding the helper in your theme.
When should I use inline-style vs. CSS?
Use inline-styles for dynamic style properties. The CSS alternative provides more advantages, such as auto-prefixing, better debugging, media queries, keyframes.