|
|
@ -5,6 +5,7 @@ Hello,
|
|
|
|
In this guide, we'll build a simple web blog in V.
|
|
|
|
In this guide, we'll build a simple web blog in V.
|
|
|
|
|
|
|
|
|
|
|
|
The benefits of using V for web:
|
|
|
|
The benefits of using V for web:
|
|
|
|
|
|
|
|
|
|
|
|
- A safe, fast, language with the development agility of Python or Ruby and
|
|
|
|
- A safe, fast, language with the development agility of Python or Ruby and
|
|
|
|
the performance of C.
|
|
|
|
the performance of C.
|
|
|
|
- Zero dependencies: everything you need for web development comes with the language
|
|
|
|
- Zero dependencies: everything you need for web development comes with the language
|
|
|
@ -15,11 +16,10 @@ in a 1 MB package.
|
|
|
|
is enough.
|
|
|
|
is enough.
|
|
|
|
- Fast development without any boilerplate.
|
|
|
|
- Fast development without any boilerplate.
|
|
|
|
|
|
|
|
|
|
|
|
*Please note that V and Vweb are at a very early stage and are changing rapidly.*
|
|
|
|
_Please note that V and Vweb are at a very early stage and are changing rapidly._
|
|
|
|
|
|
|
|
|
|
|
|
The code is available <a href='https://github.com/vlang/v/tree/master/tutorials/code/blog'>here</a>.
|
|
|
|
The code is available <a href='https://github.com/vlang/v/tree/master/tutorials/code/blog'>here</a>.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Installing V
|
|
|
|
### Installing V
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
```
|
|
|
@ -32,17 +32,15 @@ sudo ./v symlink
|
|
|
|
Now V should be globally available on your system.
|
|
|
|
Now V should be globally available on your system.
|
|
|
|
|
|
|
|
|
|
|
|
> On macOS use `v_macos.zip`, on Windows - `v_windows.zip`.
|
|
|
|
> On macOS use `v_macos.zip`, on Windows - `v_windows.zip`.
|
|
|
|
If you use a BSD system, Solaris, Android, or simply want to install V
|
|
|
|
> If you use a BSD system, Solaris, Android, or simply want to install V
|
|
|
|
from source, follow the simple instructions here:
|
|
|
|
> from source, follow the simple instructions here:
|
|
|
|
https://github.com/vlang/v#installing-v-from-source
|
|
|
|
> https://github.com/vlang/v#installing-v-from-source
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Install SQLite development dependency
|
|
|
|
### Install SQLite development dependency
|
|
|
|
|
|
|
|
|
|
|
|
If you don't have it already installed, look at the
|
|
|
|
If you don't have it already installed, look at the
|
|
|
|
[`sqlite` README](../../vlib/sqlite/README.md) for instructions.
|
|
|
|
[`sqlite` README](../../vlib/sqlite/README.md) for instructions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Creating a new Vweb project
|
|
|
|
### Creating a new Vweb project
|
|
|
|
|
|
|
|
|
|
|
|
V projects can be created anywhere and don't need to have a certain structure:
|
|
|
|
V projects can be created anywhere and don't need to have a certain structure:
|
|
|
@ -94,7 +92,6 @@ with an MVC web framework, you can think of it as a controller. (Vweb is
|
|
|
|
not an MVC framework however.) It embeds the vweb Context object, that's why we get access
|
|
|
|
not an MVC framework however.) It embeds the vweb Context object, that's why we get access
|
|
|
|
to methods like `.text()`.
|
|
|
|
to methods like `.text()`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
As you can see, there are no routing rules. The `index()` action handles the `/` request by default.
|
|
|
|
As you can see, there are no routing rules. The `index()` action handles the `/` request by default.
|
|
|
|
Vweb often uses convention over configuration and adding a new action requires
|
|
|
|
Vweb often uses convention over configuration and adding a new action requires
|
|
|
|
no routing rules either:
|
|
|
|
no routing rules either:
|
|
|
@ -109,7 +106,6 @@ fn (mut app App) time() vweb.Result {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<img width=662 src="https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_vweb/img/time.png?raw=true">
|
|
|
|
<img width=662 src="https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_vweb/img/time.png?raw=true">
|
|
|
|
|
|
|
|
|
|
|
|
> TIP: run the following command to live-reload the server: `v watch run blog.v`
|
|
|
|
> TIP: run the following command to live-reload the server: `v watch run blog.v`
|
|
|
@ -117,7 +113,6 @@ fn (mut app App) time() vweb.Result {
|
|
|
|
The `.text(string)` method returns a plain text document with the provided
|
|
|
|
The `.text(string)` method returns a plain text document with the provided
|
|
|
|
text, which isn't frequently used in websites.
|
|
|
|
text, which isn't frequently used in websites.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### HTML View
|
|
|
|
### HTML View
|
|
|
|
|
|
|
|
|
|
|
|
Let's return an HTML view instead. Create `index.html` in the same directory:
|
|
|
|
Let's return an HTML view instead. Create `index.html` in the same directory:
|
|
|
@ -129,8 +124,8 @@ Let's return an HTML view instead. Create `index.html` in the same directory:
|
|
|
|
</head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<body>
|
|
|
|
<b>@message</b>
|
|
|
|
<b>@message</b>
|
|
|
|
<br>
|
|
|
|
<br />
|
|
|
|
<img src='https://vlang.io/img/v-logo.png' width=100>
|
|
|
|
<img src="https://vlang.io/img/v-logo.png" width="100" />
|
|
|
|
</body>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
</html>
|
|
|
|
```
|
|
|
|
```
|
|
|
@ -176,7 +171,6 @@ into a single binary file together with the web application itself.
|
|
|
|
|
|
|
|
|
|
|
|
- All errors in the templates are guaranteed to be caught during compilation.
|
|
|
|
- All errors in the templates are guaranteed to be caught during compilation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Fetching data with V ORM
|
|
|
|
### Fetching data with V ORM
|
|
|
|
|
|
|
|
|
|
|
|
Now let's display some articles!
|
|
|
|
Now let's display some articles!
|
|
|
@ -184,7 +178,6 @@ Now let's display some articles!
|
|
|
|
We'll be using V's builtin ORM and a SQLite database.
|
|
|
|
We'll be using V's builtin ORM and a SQLite database.
|
|
|
|
(V ORM will also support MySQL, Postgre, and SQL Server soon.)
|
|
|
|
(V ORM will also support MySQL, Postgre, and SQL Server soon.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Add a SQLite handle to `App`:
|
|
|
|
Add a SQLite handle to `App`:
|
|
|
|
|
|
|
|
|
|
|
|
```v oksyntax
|
|
|
|
```v oksyntax
|
|
|
@ -199,14 +192,11 @@ pub mut:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In `fn main()` we'll connect to a database.
|
|
|
|
In `fn main()` we'll connect to a database.
|
|
|
|
Code in the `main()` function is run only once during app's startup, so we are going
|
|
|
|
Code in the `main()` function is run only once during app's startup, so we are going
|
|
|
|
to have one DB connection for all requests. This improves the performance of the web application,
|
|
|
|
to have one DB connection for all requests. This improves the performance of the web application,
|
|
|
|
since a DB connection doesn't have to be set up for each request.
|
|
|
|
since a DB connection doesn't have to be set up for each request.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```v oksyntax
|
|
|
|
```v oksyntax
|
|
|
|
// blog.v
|
|
|
|
// blog.v
|
|
|
|
fn main() {
|
|
|
|
fn main() {
|
|
|
@ -268,14 +258,13 @@ pub fn (app &App) index() vweb.Result {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Finally, let's update our view:
|
|
|
|
Finally, let's update our view:
|
|
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
```html
|
|
|
|
<body>
|
|
|
|
<body>
|
|
|
|
@for article in articles
|
|
|
|
@for article in articles
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<b>@article.title</b> <br>
|
|
|
|
<b>@article.title</b> <br />
|
|
|
|
@article.text
|
|
|
|
@article.text
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
@end
|
|
|
|
@end
|
|
|
@ -323,7 +312,6 @@ article := app.retrieve_article(10) or {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Adding new articles
|
|
|
|
### Adding new articles
|
|
|
|
|
|
|
|
|
|
|
|
Create `new.html`:
|
|
|
|
Create `new.html`:
|
|
|
@ -334,10 +322,10 @@ Create `new.html`:
|
|
|
|
<title>V Blog</title>
|
|
|
|
<title>V Blog</title>
|
|
|
|
</head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<body>
|
|
|
|
<form action='/new_article' method='post'>
|
|
|
|
<form action="/new_article" method="post">
|
|
|
|
<input type='text' placeholder='Title' name='title'> <br>
|
|
|
|
<input type="text" placeholder="Title" name="title" /> <br />
|
|
|
|
<textarea placeholder='Text' name='text'></textarea>
|
|
|
|
<textarea placeholder="Text" name="text"></textarea>
|
|
|
|
<input type='submit'>
|
|
|
|
<input type="submit" />
|
|
|
|
</form>
|
|
|
|
</form>
|
|
|
|
</body>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
</html>
|
|
|
@ -373,7 +361,7 @@ not necessary).
|
|
|
|
We need to update `index.html` to add a link to the "new article" page:
|
|
|
|
We need to update `index.html` to add a link to the "new article" page:
|
|
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
```html
|
|
|
|
<a href='/new'>New article</a>
|
|
|
|
<a href="/new">New article</a>
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Next we need to add the HTML endpoint to our code like we did with `index.html`:
|
|
|
|
Next we need to add the HTML endpoint to our code like we did with `index.html`:
|
|
|
@ -387,7 +375,6 @@ pub fn (mut app App) new() vweb.Result {
|
|
|
|
|
|
|
|
|
|
|
|
Re-running this code will now allow us to add new posts to our blog endpoint
|
|
|
|
Re-running this code will now allow us to add new posts to our blog endpoint
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### JSON endpoints
|
|
|
|
### JSON endpoints
|
|
|
|
|
|
|
|
|
|
|
|
This tutorial used the traditional server-side rendering. If you prefer
|
|
|
|
This tutorial used the traditional server-side rendering. If you prefer
|
|
|
@ -406,10 +393,10 @@ pub fn (mut app App) articles() vweb.Result {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<img width=662 src="https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_vweb/img/articles_json.png?raw=true">
|
|
|
|
<img width=662 src="https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_vweb/img/articles_json.png?raw=true">
|
|
|
|
|
|
|
|
|
|
|
|
### Persistent data
|
|
|
|
### Persistent data
|
|
|
|
|
|
|
|
|
|
|
|
If one wants to persist data they need to use a file instead of memory SQLite Database.
|
|
|
|
If one wants to persist data they need to use a file instead of memory SQLite Database.
|
|
|
|
Replace the db setup code with this instead:
|
|
|
|
Replace the db setup code with this instead:
|
|
|
|
|
|
|
|
|
|
|
@ -422,7 +409,6 @@ If the database file doesn't exist it will create it. The second command will
|
|
|
|
create the table `Article` if none exists already. Now every time the
|
|
|
|
create the table `Article` if none exists already. Now every time the
|
|
|
|
app is run you will see the articles created from the previous executions
|
|
|
|
app is run you will see the articles created from the previous executions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
To be continued...
|
|
|
|
To be continued...
|
|
|
|
|
|
|
|
|
|
|
|
For an example of a more sophisticated web app written in V, check out Vorum: https://github.com/vlang/vorum
|
|
|
|
For an example of a more sophisticated web app written in V, check out Vorum: https://github.com/vlang/vorum
|
|
|
|